static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch) { GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; Uint8 *blob = NULL; Uint8 *src; int srcPitch; int y; GLES_ActivateRenderer(renderer); /* Bail out if we're supposed to update an empty rectangle */ if (rect->w <= 0 || rect->h <= 0) return 0; /* Reformat the texture data into a tightly packed array */ srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format); src = (Uint8 *)pixels; if (pitch != srcPitch) { blob = (Uint8 *)SDL_malloc(srcPitch * rect->h); if (!blob) { return SDL_OutOfMemory(); } src = blob; for (y = 0; y < rect->h; ++y) { SDL_memcpy(src, pixels, srcPitch); src += srcPitch; pixels = (Uint8 *)pixels + pitch; } src = blob; } /* Create a texture subimage with the supplied data */ renderdata->glGetError(); renderdata->glEnable(data->type); renderdata->glBindTexture(data->type, data->texture); renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, rect->h, data->format, data->formattype, src); if (blob) { SDL_free(blob); } if (renderdata->glGetError() != GL_NO_ERROR) { return SDL_SetError("Failed to update texture"); } return 0; }
static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; GLES_ActivateRenderer(renderer); data->glEnable(GL_TEXTURE_2D); data->glBindTexture(texturedata->type, texturedata->texture); if(texw) *texw = (float)texturedata->texw; if(texh) *texh = (float)texturedata->texh; return 0; }
static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *data; GLint internalFormat; GLenum format, type; int texture_w, texture_h; GLenum scaleMode; GLenum result; GLES_ActivateRenderer(renderer); switch (texture->format) { case SDL_PIXELFORMAT_ABGR8888: internalFormat = GL_RGBA; format = GL_RGBA; type = GL_UNSIGNED_BYTE; break; default: return SDL_SetError("Texture format not supported"); } data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { return SDL_OutOfMemory(); } if (texture->access == SDL_TEXTUREACCESS_STREAMING) { data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); data->pixels = SDL_calloc(1, texture->h * data->pitch); if (!data->pixels) { SDL_free(data); return SDL_OutOfMemory(); } } if (texture->access == SDL_TEXTUREACCESS_TARGET) { if (!renderdata->GL_OES_framebuffer_object_supported) { SDL_free(data); return SDL_SetError("GL_OES_framebuffer_object not supported"); } data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h); } else { data->fbo = NULL; } renderdata->glGetError(); renderdata->glEnable(GL_TEXTURE_2D); renderdata->glGenTextures(1, &data->texture); result = renderdata->glGetError(); if (result != GL_NO_ERROR) { SDL_free(data); return GLES_SetError("glGenTextures()", result); } data->type = GL_TEXTURE_2D; /* no NPOV textures allowed in OpenGL ES (yet) */ texture_w = power_of_2(texture->w); texture_h = power_of_2(texture->h); data->texw = (GLfloat) texture->w / texture_w; data->texh = (GLfloat) texture->h / texture_h; data->format = format; data->formattype = type; scaleMode = GetScaleQuality(); renderdata->glBindTexture(data->type, data->texture); renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode); renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0, format, type, NULL); renderdata->glDisable(GL_TEXTURE_2D); result = renderdata->glGetError(); if (result != GL_NO_ERROR) { SDL_free(data); return GLES_SetError("glTexImage2D()", result); } texture->driverdata = data; return 0; }
static int GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_FRect * dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; GLfloat minx, miny, maxx, maxy; GLfloat minu, maxu, minv, maxv; GLfloat centerx, centery; GLfloat vertices[8]; GLfloat texCoords[8]; GLES_ActivateRenderer(renderer); data->glEnable(GL_TEXTURE_2D); data->glBindTexture(texturedata->type, texturedata->texture); if (texture->modMode) { GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a); } else { GLES_SetColor(data, 255, 255, 255, 255); } GLES_SetBlendMode(data, texture->blendMode); GLES_SetTexCoords(data, SDL_TRUE); centerx = center->x; centery = center->y; /* Rotate and translate */ data->glPushMatrix(); data->glTranslatef(dstrect->x + centerx, dstrect->y + centery, 0.0f); data->glRotatef((GLfloat)angle, 0.0f, 0.0f, 1.0f); if (flip & SDL_FLIP_HORIZONTAL) { minx = dstrect->w - centerx; maxx = -centerx; } else { minx = -centerx; maxx = dstrect->w - centerx; } if (flip & SDL_FLIP_VERTICAL) { miny = dstrect->h - centery; maxy = -centery; } else { miny = -centery; maxy = dstrect->h - centery; } minu = (GLfloat) srcrect->x / texture->w; minu *= texturedata->texw; maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; maxu *= texturedata->texw; minv = (GLfloat) srcrect->y / texture->h; minv *= texturedata->texh; maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; maxv *= texturedata->texh; vertices[0] = minx; vertices[1] = miny; vertices[2] = maxx; vertices[3] = miny; vertices[4] = minx; vertices[5] = maxy; vertices[6] = maxx; vertices[7] = maxy; texCoords[0] = minu; texCoords[1] = minv; texCoords[2] = maxu; texCoords[3] = minv; texCoords[4] = minu; texCoords[5] = maxv; texCoords[6] = maxu; texCoords[7] = maxv; data->glVertexPointer(2, GL_FLOAT, 0, vertices); data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords); data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); data->glPopMatrix(); data->glDisable(GL_TEXTURE_2D); return 0; }
static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_FRect * dstrect) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; GLfloat minx, miny, maxx, maxy; GLfloat minu, maxu, minv, maxv; GLfloat vertices[8]; GLfloat texCoords[8]; GLES_ActivateRenderer(renderer); data->glEnable(GL_TEXTURE_2D); data->glBindTexture(texturedata->type, texturedata->texture); if (texture->modMode) { GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a); } else { GLES_SetColor(data, 255, 255, 255, 255); } GLES_SetBlendMode(data, texture->blendMode); GLES_SetTexCoords(data, SDL_TRUE); minx = dstrect->x; miny = dstrect->y; maxx = dstrect->x + dstrect->w; maxy = dstrect->y + dstrect->h; minu = (GLfloat) srcrect->x / texture->w; minu *= texturedata->texw; maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; maxu *= texturedata->texw; minv = (GLfloat) srcrect->y / texture->h; minv *= texturedata->texh; maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; maxv *= texturedata->texh; vertices[0] = minx; vertices[1] = miny; vertices[2] = maxx; vertices[3] = miny; vertices[4] = minx; vertices[5] = maxy; vertices[6] = maxx; vertices[7] = maxy; texCoords[0] = minu; texCoords[1] = minv; texCoords[2] = maxu; texCoords[3] = minv; texCoords[4] = minu; texCoords[5] = maxv; texCoords[6] = maxu; texCoords[7] = maxv; data->glVertexPointer(2, GL_FLOAT, 0, vertices); data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords); data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); data->glDisable(GL_TEXTURE_2D); return 0; }
static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; int minx, miny, maxx, maxy; GLfloat minu, maxu, minv, maxv; GLES_ActivateRenderer(renderer); data->glEnable(GL_TEXTURE_2D); data->glBindTexture(texturedata->type, texturedata->texture); if (texture->modMode) { GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a); } else { GLES_SetColor(data, 255, 255, 255, 255); } GLES_SetBlendMode(data, texture->blendMode); GLES_SetTexCoords(data, SDL_TRUE); if (data->GL_OES_draw_texture_supported && data->useDrawTexture) { /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */ GLint cropRect[4]; int w, h; SDL_Window *window = renderer->window; SDL_GetWindowSize(window, &w, &h); if (renderer->target) { cropRect[0] = srcrect->x; cropRect[1] = srcrect->y; cropRect[2] = srcrect->w; cropRect[3] = srcrect->h; data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); data->glDrawTexiOES(renderer->viewport.x + dstrect->x, renderer->viewport.y + dstrect->y, 0, dstrect->w, dstrect->h); } else { cropRect[0] = srcrect->x; cropRect[1] = srcrect->y + srcrect->h; cropRect[2] = srcrect->w; cropRect[3] = -srcrect->h; data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); data->glDrawTexiOES(renderer->viewport.x + dstrect->x, h - (renderer->viewport.y + dstrect->y) - dstrect->h, 0, dstrect->w, dstrect->h); } } else { minx = dstrect->x; miny = dstrect->y; maxx = dstrect->x + dstrect->w; maxy = dstrect->y + dstrect->h; minu = (GLfloat) srcrect->x / texture->w; minu *= texturedata->texw; maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; maxu *= texturedata->texw; minv = (GLfloat) srcrect->y / texture->h; minv *= texturedata->texh; maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; maxv *= texturedata->texh; GLshort vertices[8]; GLfloat texCoords[8]; vertices[0] = minx; vertices[1] = miny; vertices[2] = maxx; vertices[3] = miny; vertices[4] = minx; vertices[5] = maxy; vertices[6] = maxx; vertices[7] = maxy; texCoords[0] = minu; texCoords[1] = minv; texCoords[2] = maxu; texCoords[3] = minv; texCoords[4] = minu; texCoords[5] = maxv; texCoords[6] = maxu; texCoords[7] = maxv; data->glVertexPointer(2, GL_SHORT, 0, vertices); data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords); data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } data->glDisable(GL_TEXTURE_2D); return 0; }
static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; int minx, miny, maxx, maxy; GLfloat minu, maxu, minv, maxv; int i; void *temp_buffer; /* used for reformatting dirty rect pixels */ void *temp_ptr; data->glEnable(GL_TEXTURE_2D); if (texturedata->dirty.list) { SDL_DirtyRect *dirty; void *pixels; int bpp = SDL_BYTESPERPIXEL(texture->format); int pitch = texturedata->pitch; SetupTextureUpdate(data, texture, pitch); data->glBindTexture(texturedata->type, texturedata->texture); for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) { SDL_Rect *rect = &dirty->rect; pixels = (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch + rect->x * bpp); /* There is no GL_UNPACK_ROW_LENGTH in OpenGLES we must do this reformatting ourselves(!) maybe it'd be a good idea to keep a temp buffer around for this purpose rather than allocating it each time */ temp_buffer = SDL_malloc(rect->w * rect->h * bpp); temp_ptr = temp_buffer; for (i = 0; i < rect->h; i++) { SDL_memcpy(temp_ptr, pixels, rect->w * bpp); temp_ptr += rect->w * bpp; pixels += pitch; } data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y, rect->w, rect->h, texturedata->format, texturedata->formattype, temp_buffer); SDL_free(temp_buffer); } SDL_ClearDirtyRects(&texturedata->dirty); } data->glBindTexture(texturedata->type, texturedata->texture); if (texture->modMode) { data->glColor4f((GLfloat) texture->r * inv255f, (GLfloat) texture->g * inv255f, (GLfloat) texture->b * inv255f, (GLfloat) texture->a * inv255f); } else { data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } GLES_SetBlendMode(data, texture->blendMode, 0); switch (texture->scaleMode) { case SDL_TEXTURESCALEMODE_NONE: case SDL_TEXTURESCALEMODE_FAST: data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; case SDL_TEXTURESCALEMODE_SLOW: case SDL_TEXTURESCALEMODE_BEST: data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; } if (data->GL_OES_draw_texture_supported && data->useDrawTexture) { /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */ SDL_Window *window = renderer->window; GLint cropRect[4]; cropRect[0] = srcrect->x; cropRect[1] = srcrect->y + srcrect->h; cropRect[2] = srcrect->w; cropRect[3] = -srcrect->h; data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); data->glDrawTexiOES(dstrect->x, window->h - dstrect->y - dstrect->h, 0, dstrect->w, dstrect->h); } else { minx = dstrect->x; miny = dstrect->y; maxx = dstrect->x + dstrect->w; maxy = dstrect->y + dstrect->h; minu = (GLfloat) srcrect->x / texture->w; minu *= texturedata->texw; maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; maxu *= texturedata->texw; minv = (GLfloat) srcrect->y / texture->h; minv *= texturedata->texh; maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; maxv *= texturedata->texh; GLshort vertices[8]; GLfloat texCoords[8]; vertices[0] = minx; vertices[1] = miny; vertices[2] = maxx; vertices[3] = miny; vertices[4] = minx; vertices[5] = maxy; vertices[6] = maxx; vertices[7] = maxy; texCoords[0] = minu; texCoords[1] = minv; texCoords[2] = maxu; texCoords[3] = minv; texCoords[4] = minu; texCoords[5] = maxv; texCoords[6] = maxu; texCoords[7] = maxv; data->glVertexPointer(2, GL_SHORT, 0, vertices); data->glEnableClientState(GL_VERTEX_ARRAY); data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords); data->glEnableClientState(GL_TEXTURE_COORD_ARRAY); data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); data->glDisableClientState(GL_TEXTURE_COORD_ARRAY); data->glDisableClientState(GL_VERTEX_ARRAY); } data->glDisable(GL_TEXTURE_2D); return 0; }
static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *data; GLint internalFormat; GLenum format, type; int texture_w, texture_h; GLenum result; switch (texture->format) { case SDL_PIXELFORMAT_BGR24: internalFormat = GL_RGB; format = GL_RGB; type = GL_UNSIGNED_BYTE; break; case SDL_PIXELFORMAT_ABGR8888: internalFormat = GL_RGBA; format = GL_RGBA; type = GL_UNSIGNED_BYTE; break; case SDL_PIXELFORMAT_BGR565: internalFormat = GL_RGB; format = GL_RGB; type = GL_UNSIGNED_SHORT_5_6_5; break; case SDL_PIXELFORMAT_ABGR1555: internalFormat = GL_RGBA; format = GL_RGBA; type = GL_UNSIGNED_SHORT_5_5_5_1; break; case SDL_PIXELFORMAT_ABGR4444: internalFormat = GL_RGBA; format = GL_RGBA; type = GL_UNSIGNED_SHORT_4_4_4_4; break; default: SDL_SetError("Unsupported by OpenGL ES texture format"); return -1; } data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } if (texture->access == SDL_TEXTUREACCESS_STREAMING) { data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); data->pixels = SDL_malloc(texture->h * data->pitch); if (!data->pixels) { SDL_OutOfMemory(); SDL_free(data); return -1; } } texture->driverdata = data; renderdata->glGetError(); renderdata->glEnable(GL_TEXTURE_2D); renderdata->glGenTextures(1, &data->texture); data->type = GL_TEXTURE_2D; /* no NPOV textures allowed in OpenGL ES (yet) */ texture_w = power_of_2(texture->w); texture_h = power_of_2(texture->h); data->texw = (GLfloat) texture->w / texture_w; data->texh = (GLfloat) texture->h / texture_h; data->format = format; data->formattype = type; renderdata->glBindTexture(data->type, data->texture); renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0, format, type, NULL); renderdata->glDisable(GL_TEXTURE_2D); result = renderdata->glGetError(); if (result != GL_NO_ERROR) { GLES_SetError("glTexImage2D()", result); return -1; } return 0; }
static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *data; GLint internalFormat; GLenum format, type; int texture_w, texture_h; GLenum result; switch (texture->format) { case SDL_PIXELFORMAT_RGB24: internalFormat = GL_RGB; format = GL_RGB; type = GL_UNSIGNED_BYTE; break; case SDL_PIXELFORMAT_BGR888: case SDL_PIXELFORMAT_ABGR8888: internalFormat = GL_RGBA; format = GL_RGBA; type = GL_UNSIGNED_BYTE; break; case SDL_PIXELFORMAT_RGB565: internalFormat = GL_RGB; format = GL_RGB; type = GL_UNSIGNED_SHORT_5_6_5; break; case SDL_PIXELFORMAT_RGBA5551: internalFormat = GL_RGBA; format = GL_RGBA; type = GL_UNSIGNED_SHORT_5_5_5_1; break; case SDL_PIXELFORMAT_RGBA4444: internalFormat = GL_RGBA; format = GL_RGBA; type = GL_UNSIGNED_SHORT_4_4_4_4; break; default: SDL_SetError("Texture format %s not supported by OpenGL ES", SDL_GetPixelFormatName(texture->format)); return -1; } data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } if (texture->access == SDL_TEXTUREACCESS_STREAMING) { data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); data->pixels = SDL_malloc(texture->h * data->pitch); if (!data->pixels) { SDL_OutOfMemory(); SDL_free(data); return -1; } } texture->driverdata = data; renderdata->glGetError(); renderdata->glEnable(GL_TEXTURE_2D); renderdata->glGenTextures(1, &data->texture); data->type = GL_TEXTURE_2D; /* no NPOV textures allowed in OpenGL ES (yet) */ texture_w = power_of_2(texture->w); texture_h = power_of_2(texture->h); data->texw = (GLfloat) texture->w / texture_w; data->texh = (GLfloat) texture->h / texture_h; if( renderer->info.max_texture_width < texture_w || renderer->info.max_texture_height < texture_h ) __android_log_print(ANDROID_LOG_WARN, "libSDL", "GLES: Allocated texture of size %dx%d which is bigger than largest possible device texture %dx%d", texture_w, texture_h, renderer->info.max_texture_width, renderer->info.max_texture_height ); else if( texture_w > 1024 || texture_h > 1024 ) __android_log_print(ANDROID_LOG_WARN, "libSDL", "GLES: Allocated texture of size %dx%d which is bigger than 1024x1024 - this code will not work on HTC G1", texture_w, texture_h ); data->format = format; data->formattype = type; renderdata->glBindTexture(data->type, data->texture); renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0, format, type, NULL); renderdata->glDisable(GL_TEXTURE_2D); result = renderdata->glGetError(); if (result != GL_NO_ERROR) { GLES_SetError("glTexImage2D()", result); return -1; } return 0; }