31 #include "util/structures/rect.h"
32 #include "video/imagemanager.h"
33 #include "video/sdl/sdlimage.h"
34 #include "video/opengle/renderbackendopengle.h"
39 GLeImage::GLeImage(IResourceLoader* loader):
47 GLeImage::GLeImage(
const std::string& name, IResourceLoader* loader):
55 GLeImage::GLeImage(SDL_Surface* surface):
63 GLeImage::GLeImage(
const std::string& name, SDL_Surface* surface):
71 GLeImage::GLeImage(
const uint8_t* data, uint32_t width, uint32_t height):
72 Image(data, width, height),
80 GLeImage::GLeImage(
const std::string& name,
const uint8_t* data, uint32_t width, uint32_t height):
81 Image(name, data, width, height),
89 GLeImage::~GLeImage() {
102 void GLeImage::resetGlimage() {
108 m_colorkey = RenderBackend::instance()->getColorKey();
111 void GLeImage::cleanup() {
114 glDeleteTextures(1, &m_texId);
117 m_compressed =
false;
120 m_tex_coords[0] = m_tex_coords[1] =
121 m_tex_coords[2] = m_tex_coords[3] = 0.0f;
124 bool GLeImage::renderCheck(
const Rect& rect, uint8_t alpha) {
129 RenderBackend* rb = RenderBackend::instance();
130 SDL_Surface* target = rb->getRenderTargetSurface();
131 assert(target != m_surface);
134 if (rect.right() < 0 || rect.x >
static_cast<int32_t
>(target->w) ||
135 rect.bottom() < 0 || rect.y >
static_cast<int32_t
>(target->h)) {
141 }
else if (m_shared) {
148 if(renderCheck(rect, alpha)) {
150 RenderBackend::instance()->addImageToArray(m_texId, rect, m_tex_coords, alpha, NULL);
154 void GLeImage::renderZ(
const Rect& rect,
float vertexZ, uint8_t alpha,
bool forceNewBatch, uint8_t
const* rgb) {
155 if(renderCheck(rect, alpha)) {
157 m_texId, rect, vertexZ, m_tex_coords, alpha, forceNewBatch, rgb);
161 void GLeImage::generateGLTexture() {
168 const uint32_t width = m_surface->w;
169 const uint32_t height = m_surface->h;
173 if(GLEE_ARB_texture_non_power_of_two && RenderBackend::instance()->isNPOTEnabled()) {
174 m_chunk_size_w = width;
175 m_chunk_size_h = height;
184 m_tex_coords[0] = m_tex_coords[1] = 0.0f;
185 m_tex_coords[2] =
static_cast<float>(m_surface->w%m_chunk_size_w) / static_cast<float>(m_chunk_size_w);
186 m_tex_coords[3] =
static_cast<float>(m_surface->h%m_chunk_size_h) / static_cast<float>(m_chunk_size_h);
188 if (m_tex_coords[2] == 0.0f){
189 m_tex_coords[2] = 1.0f;
192 if (m_tex_coords[3] == 0.0f){
193 m_tex_coords[3] = 1.0f;
196 uint8_t* data =
static_cast<uint8_t*
>(m_surface->pixels);
197 int32_t pitch = m_surface->pitch;
202 glGenTextures(1, &m_texId);
204 static_cast<RenderBackendOpenGLe*
>(RenderBackend::instance())->bindTexture(m_texId);
206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
209 GLint internalFormat = GL_RGBA8;
210 if(GLEE_ARB_texture_compression && RenderBackend::instance()->isImageCompressingEnabled()) {
211 internalFormat = GL_COMPRESSED_RGBA;
214 m_compressed =
false;
217 SDL_Surface* target = RenderBackend::instance()->getRenderTargetSurface();
218 int32_t bpp_target = target->format->BitsPerPixel;
219 int32_t bpp_source = m_surface->format->BitsPerPixel;
221 if (bpp_target == 16 && bpp_source == 32) {
222 uint16_t* oglbuffer =
new uint16_t[m_chunk_size_w * m_chunk_size_h];
223 memset(oglbuffer, 0x00, m_chunk_size_w*m_chunk_size_h*
sizeof(uint16_t));
225 for (uint32_t y = 0; y < height; ++y) {
226 for (uint32_t x = 0; x < width; ++x) {
227 uint32_t pos = (y * pitch) + (x * 4);
229 uint8_t r = data[pos + 0];
230 uint8_t g = data[pos + 1];
231 uint8_t b = data[pos + 2];
232 uint8_t a = data[pos + 3];
234 if (RenderBackend::instance()->isColorKeyEnabled()) {
236 if (r == m_colorkey.r && g == m_colorkey.g && b == m_colorkey.b) {
241 oglbuffer[(y*m_chunk_size_w) + x] = ((r >> 4) << 12) |
249 internalFormat = GL_RGBA4;
253 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_chunk_size_w, m_chunk_size_h,
254 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, oglbuffer);
260 if(GLEE_ARB_texture_non_power_of_two && RenderBackend::instance()->isNPOTEnabled()) {
261 if(RenderBackend::instance()->isColorKeyEnabled()) {
262 uint8_t* oglbuffer =
new uint8_t[width * height * 4];
263 memcpy(oglbuffer, data, width * height * 4 *
sizeof(uint8_t));
265 for (uint32_t y = 0; y < height; ++y) {
266 for (uint32_t x = 0; x < width * 4; x += 4) {
267 uint32_t gid = x + y * width;
269 uint8_t r = oglbuffer[gid + 0];
270 uint8_t g = oglbuffer[gid + 1];
271 uint8_t b = oglbuffer[gid + 2];
272 uint8_t a = oglbuffer[gid + 3];
275 if (r == m_colorkey.r && g == m_colorkey.g && b == m_colorkey.b) {
276 oglbuffer[gid + 3] = 0;
282 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_chunk_size_w, m_chunk_size_h,
283 0, GL_RGBA, GL_UNSIGNED_BYTE, oglbuffer);
289 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_chunk_size_w, m_chunk_size_h,
290 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
294 uint32_t* oglbuffer =
new uint32_t[m_chunk_size_w * m_chunk_size_h];
295 memset(oglbuffer, 0x00, m_chunk_size_w*m_chunk_size_h*
sizeof(uint32_t));
297 for (uint32_t y = 0; y < height; ++y) {
298 for (uint32_t x = 0; x < width; ++x) {
299 uint32_t pos = (y * pitch) + (x * 4);
301 uint8_t a = data[pos + 3];
302 uint8_t b = data[pos + 2];
303 uint8_t g = data[pos + 1];
304 uint8_t r = data[pos + 0];
306 if (RenderBackend::instance()->isColorKeyEnabled()) {
308 if (r == m_colorkey.r && g == m_colorkey.g && b == m_colorkey.b) {
313 oglbuffer[(y*m_chunk_size_w) + x] = r | (g << 8) | (b << 16) | (a<<24);
318 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_chunk_size_w, m_chunk_size_h,
319 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLvoid*>(oglbuffer));
325 void GLeImage::generateGLSharedTexture(
const GLeImage* shared,
const Rect& region) {
326 uint32_t width = shared->getWidth();
327 uint32_t height = shared->getHeight();
329 if(!GLEE_ARB_texture_non_power_of_two || !RenderBackend::instance()->isNPOTEnabled()) {
334 m_tex_coords[0] =
static_cast<GLfloat
>(region.x) / static_cast<GLfloat>(width);
335 m_tex_coords[1] =
static_cast<GLfloat
>(region.y) / static_cast<GLfloat>(height);
336 m_tex_coords[2] =
static_cast<GLfloat
>(region.x + region.w) / static_cast<GLfloat>(width);
337 m_tex_coords[3] =
static_cast<GLfloat
>(region.y + region.h) / static_cast<GLfloat>(height);
344 m_texId = img->m_texId;
346 m_subimagerect = region;
347 m_atlas_img = shared;
348 m_surface = m_shared_img->m_surface;
349 m_compressed = m_shared_img->m_compressed;
350 m_atlas_name = m_shared_img->getName();
353 generateGLSharedTexture(img, region);
356 setState(IResource::RES_LOADED);
362 }
else if (m_shared) {
367 void GLeImage::validateShared() {
369 if (m_shared_img->m_texId && m_shared_img->m_texId == m_texId) {
373 if (m_shared_img->getState() == IResource::RES_NOT_LOADED) {
374 m_shared_img->load();
375 m_shared_img->generateGLTexture();
378 m_texId = m_shared_img->m_texId;
379 m_surface = m_shared_img->m_surface;
380 m_compressed = m_shared_img->m_compressed;
381 generateGLSharedTexture(m_shared_img, m_subimagerect);
389 glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, img->getWidth(), img->getHeight(),
390 GL_RGBA, GL_UNSIGNED_BYTE, img->getSurface()->pixels);
394 void GLeImage::load() {
398 if (!ImageManager::instance()->exists(m_atlas_name)) {
399 ImagePtr newAtlas = ImageManager::instance()->create(m_atlas_name);
401 m_atlas_img = newAtlas;
406 if (m_shared_img->m_surface != m_surface || m_texId != m_shared_img->m_texId) {
407 m_texId = m_shared_img->m_texId;
408 m_surface = m_shared_img->m_surface;
409 m_compressed = m_shared_img->m_compressed;
411 generateGLSharedTexture(m_shared_img, m_subimagerect);
414 m_state = IResource::RES_LOADED;
420 void GLeImage::free() {
422 m_state = IResource::RES_NOT_LOADED;
425 GLuint GLeImage::getTexId()
const {
429 const GLfloat* GLeImage::getTexCoords()
const {
void reset(SDL_Surface *surface)
virtual void setSurface(SDL_Surface *surface)
unsigned nextPow2(unsigned x)
virtual void useSharedImage(const ImagePtr &shared, const Rect ®ion)
virtual void copySubimage(uint32_t xoffset, uint32_t yoffset, const ImagePtr &img)
virtual void copySubimage(uint32_t xoffset, uint32_t yoffset, const ImagePtr &img)
virtual void forceLoadInternal()
virtual void render(const Rect &rect, uint8_t alpha=255, uint8_t const *rgb=0)
virtual void invalidate()
credit to phoku for his NodeDisplay example which the visitor code is adapted from ( he coded the qua...