1 /***************************************************************************
2  *   Copyright (C) 2005-2019 by the FIFE team                              *
3  *   http://www.fifengine.net                                              *
4  *   This file is part of FIFE.                                            *
5  *                                                                         *
6  *   FIFE is free software; you can redistribute it and/or                 *
7  *   modify it under the terms of the GNU Lesser General Public            *
8  *   License as published by the Free Software Foundation; either          *
9  *   version 2.1 of the License, or (at your option) any later version.    *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the                 *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // 3rd party library includes
25 
26 // FIFE includes
27 // These includes are split up in two parts, separated by one empty line
28 // First block: files included from the FIFE root src directory
29 // Second block: files included from the same folder
30 #include "video/imagemanager.h"
31 #include "video/opengl/glimage.h"
32 
33 #include "librocketrenderinterface.h"
34 
35 namespace FIFE {
36 
LibRocketRenderInterface()37 	LibRocketRenderInterface::LibRocketRenderInterface()
38 	:
39 	m_renderBackend(RenderBackend::instance()),
40 	m_imageManager(ImageManager::instance()) {
41 	}
42 
~LibRocketRenderInterface()43 	LibRocketRenderInterface::~LibRocketRenderInterface() {
44 		freeTextures();
45 	}
46 
RenderGeometry(Rocket::Core::Vertex * vertices,int num_vertices,int * indices,int num_indices,Rocket::Core::TextureHandle texture,const Rocket::Core::Vector2f & translation)47 	void LibRocketRenderInterface::RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation) {
48 
49 		GeometryCallData geometryCallData;
50 
51 		geometryCallData.vertices.reserve(num_vertices);
52 		for(int i = 0; i < num_vertices; i++) {
53 			GuiVertex vertex;
54 
55 			vertex.position.set(vertices[i].position.x, vertices[i].position.y);
56 			vertex.color.set(vertices[i].colour.red, vertices[i].colour.green, vertices[i].colour.blue, vertices[i].colour.alpha);
57 			vertex.texCoords.set(vertices[i].tex_coord.x, vertices[i].tex_coord.y);
58 
59 			geometryCallData.vertices.push_back(vertex);
60 		}
61 
62 		geometryCallData.indices.reserve(num_indices);
63 		for(int i = 0; i < num_indices; i++) {
64 			geometryCallData.indices.push_back(indices[i]);
65 		}
66 
67 		geometryCallData.textureHandle = texture;
68 		geometryCallData.translation.set(translation.x, translation.y);
69 
70 		if(m_geometryCalls.empty()) {
71 			GeometryCall geometryCall;
72 
73 			geometryCall.callChain.push(geometryCallData);
74 			m_geometryCalls.push(geometryCall);
75 		} else {
76 			GeometryCall& geometryCall = m_geometryCalls.back();
77 
78 			geometryCall.callChain.push(geometryCallData);
79 		}
80 	}
81 
CompileGeometry(Rocket::Core::Vertex * vertices,int num_vertices,int * indices,int num_indices,Rocket::Core::TextureHandle texture)82 	Rocket::Core::CompiledGeometryHandle LibRocketRenderInterface::CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture) {
83 		return (Rocket::Core::CompiledGeometryHandle) NULL;
84 	}
85 
RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry,const Rocket::Core::Vector2f & translation)86 	void LibRocketRenderInterface::RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation) {
87 	}
88 
ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle ROCKET_UNUSED (geometry))89 	void LibRocketRenderInterface::ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle ROCKET_UNUSED(geometry)) {
90 	}
91 
EnableScissorRegion(bool enable)92 	void LibRocketRenderInterface::EnableScissorRegion(bool enable) {
93 		GeometryCall gc;
94 
95 		gc.enableScissorTest = enable;
96 
97 		//check if there is a previous call and has a clip area enabled
98 		if(!m_geometryCalls.empty()) {
99 			GeometryCall& prevgc = m_geometryCalls.back();
100 
101 			if(prevgc.hasScissorArea) {
102 				gc.hasScissorArea = true;
103 				gc.scissorArea = prevgc.scissorArea;
104 			}
105 		}
106 
107 		m_geometryCalls.push(gc);
108 	}
109 
SetScissorRegion(int x,int y,int width,int height)110 	void LibRocketRenderInterface::SetScissorRegion(int x, int y, int width, int height) {
111 		GeometryCall gc;
112 
113 		gc.hasScissorArea = true;
114 		gc.scissorArea = Rect(x, y, width, height);
115 
116 		//check if there is a previous call and has scissors enabled
117 		if(!m_geometryCalls.empty()) {
118 			GeometryCall& prevgc = m_geometryCalls.back();
119 
120 			gc.enableScissorTest = prevgc.enableScissorTest;
121 		}
122 
123 		m_geometryCalls.push(gc);
124 	}
125 
LoadTexture(Rocket::Core::TextureHandle & texture_handle,Rocket::Core::Vector2i & texture_dimensions,const Rocket::Core::String & source)126 	bool LibRocketRenderInterface::LoadTexture(Rocket::Core::TextureHandle& texture_handle, Rocket::Core::Vector2i& texture_dimensions, const Rocket::Core::String& source) {
127 
128 		std::string filename(source.CString());
129 
130 		ImagePtr loadedTexture = m_imageManager->exists(filename) ?
131 		                         m_imageManager->get(filename) :
132 		                         m_imageManager->load(filename);
133 
134 		texture_handle = static_cast<Rocket::Core::TextureHandle>(loadedTexture->getHandle());
135 		texture_dimensions.x = loadedTexture->getWidth();
136 		texture_dimensions.y = loadedTexture->getHeight();
137 
138 		return true;
139 	}
140 
GenerateTexture(Rocket::Core::TextureHandle & texture_handle,const Rocket::Core::byte * source,const Rocket::Core::Vector2i & source_dimensions)141 	bool LibRocketRenderInterface::GenerateTexture(Rocket::Core::TextureHandle& texture_handle, const Rocket::Core::byte* source, const Rocket::Core::Vector2i& source_dimensions) {
142 
143 		Image* generatedTexture = m_renderBackend->createImage(source, source_dimensions.x, source_dimensions.y);
144 
145 		generatedTexture->setState(IResource::RES_LOADED);
146 		m_imageManager->add(generatedTexture);
147 
148 		texture_handle = static_cast<Rocket::Core::TextureHandle>(generatedTexture->getHandle());
149 
150 		return true;
151 	}
152 
ReleaseTexture(Rocket::Core::TextureHandle texture_handle)153 	void LibRocketRenderInterface::ReleaseTexture(Rocket::Core::TextureHandle texture_handle) {
154 
155 		ResourceHandle rh = static_cast<ResourceHandle>(texture_handle);
156 		m_freedTextures.push_back(rh);
157 	}
158 
render()159 	void LibRocketRenderInterface::render() {
160 
161 		while(!m_geometryCalls.empty()) {
162 			GeometryCall& geometryCall = m_geometryCalls.front();
163 
164 			if(geometryCall.hasScissorArea) {
165 				m_renderBackend->pushClipArea(geometryCall.scissorArea, false);
166 			}
167 
168 			if(geometryCall.enableScissorTest) {
169 				m_renderBackend->enableScissorTest();
170 			} else {
171 				m_renderBackend->disableScissorTest();
172 			}
173 
174 			while(!geometryCall.callChain.empty()) {
175 				GeometryCallData& geometryCallData = geometryCall.callChain.front();
176 
177 				ImagePtr img = m_imageManager->get(geometryCallData.textureHandle);
178 
179 				m_renderBackend->renderGuiGeometry(geometryCallData.vertices, geometryCallData.indices, geometryCallData.translation, img);
180 
181 				geometryCall.callChain.pop();
182 			}
183 
184 			if(geometryCall.hasScissorArea) {
185 				m_renderBackend->popClipArea();
186 			}
187 
188 			m_geometryCalls.pop();
189 		}
190 	}
191 
freeTextures()192 	void LibRocketRenderInterface::freeTextures() {
193 		std::list<ResourceHandle>::iterator it(m_freedTextures.begin());
194 		std::list<ResourceHandle>::iterator end(m_freedTextures.end());
195 
196 		for(; it != end; ++it) {
197 			ResourceHandle rh = (*it);
198 			ImagePtr texture = m_imageManager->get(rh);
199 			texture->free();
200 		}
201 
202 		std::list<ResourceHandle> temp;
203 		m_freedTextures.swap(temp);
204 	}
205 };