static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch) { GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; GL_TextureData *data = (GL_TextureData *) texture->driverdata; GLenum result; GL_ActivateRenderer(renderer); renderdata->glGetError(); renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / SDL_BYTESPERPIXEL(texture->format))); renderdata->glEnable(data->type); renderdata->glBindTexture(data->type, data->texture); renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, rect->h, data->format, data->formattype, pixels); if (data->yuv) { const void *top; renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2)); /* Skip to the top of the next texture */ top = (const void*)((const Uint8*)pixels + (texture->h-rect->y) * pitch - rect->x); /* Skip to the correct offset into the next texture */ pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2); if (texture->format == SDL_PIXELFORMAT_YV12) { renderdata->glBindTexture(data->type, data->vtexture); } else { renderdata->glBindTexture(data->type, data->utexture); } renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, rect->w/2, rect->h/2, data->format, data->formattype, pixels); /* Skip to the top of the next texture */ top = (const void*)((const Uint8*)top + (texture->h * pitch)/4); /* Skip to the correct offset into the next texture */ pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2); if (texture->format == SDL_PIXELFORMAT_YV12) { renderdata->glBindTexture(data->type, data->utexture); } else { renderdata->glBindTexture(data->type, data->vtexture); } renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, rect->w/2, rect->h/2, data->format, data->formattype, pixels); } renderdata->glDisable(data->type); result = renderdata->glGetError(); if (result != GL_NO_ERROR) { GL_SetError("glTexSubImage2D()", result); return -1; } return 0; }
static void GL_RenderPresent(SDL_Renderer * renderer) { GL_ActivateRenderer(renderer); SDL_GL_SwapWindow(renderer->window); }
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 pixel_format, void * pixels, int pitch) { GL_RenderData *data = (GL_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; Uint32 temp_format = SDL_PIXELFORMAT_ARGB8888; void *temp_pixels; int temp_pitch; GLint internalFormat; GLenum format, type; Uint8 *src, *dst, *tmp; int w, h, length, rows; int status; GL_ActivateRenderer(renderer); temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format); temp_pixels = SDL_malloc(rect->h * temp_pitch); if (!temp_pixels) { SDL_OutOfMemory(); return -1; } convert_format(data, temp_format, &internalFormat, &format, &type); SDL_GetWindowSize(window, &w, &h); data->glPixelStorei(GL_PACK_ALIGNMENT, 1); data->glPixelStorei(GL_PACK_ROW_LENGTH, (temp_pitch / SDL_BYTESPERPIXEL(temp_format))); data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h, format, type, temp_pixels); /* Flip the rows to be top-down */ length = rect->w * SDL_BYTESPERPIXEL(temp_format); src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch; dst = (Uint8*)temp_pixels; tmp = SDL_stack_alloc(Uint8, length); rows = rect->h / 2; while (rows--) { SDL_memcpy(tmp, dst, length); SDL_memcpy(dst, src, length); SDL_memcpy(src, tmp, length); dst += temp_pitch; src -= temp_pitch; } SDL_stack_free(tmp); status = SDL_ConvertPixels(rect->w, rect->h, temp_format, temp_pixels, temp_pitch, pixel_format, pixels, pitch); SDL_free(temp_pixels); return status; }
static int GL_RenderClear(SDL_Renderer * renderer) { GL_RenderData *data = (GL_RenderData *) renderer->driverdata; GL_ActivateRenderer(renderer); data->glClearColor((GLfloat) renderer->r * inv255f, (GLfloat) renderer->g * inv255f, (GLfloat) renderer->b * inv255f, (GLfloat) renderer->a * inv255f); data->glClear(GL_COLOR_BUFFER_BIT); return 0; }
static void GL_SetDrawingState(SDL_Renderer * renderer) { GL_RenderData *data = (GL_RenderData *) renderer->driverdata; GL_ActivateRenderer(renderer); GL_SetColor(data, renderer->r, renderer->g, renderer->b, renderer->a); GL_SetBlendMode(data, renderer->blendMode); GL_SetShader(data, SHADER_SOLID); }
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 pixel_format, void * pixels, int pitch) { GL_RenderData *data = (GL_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; GLint internalFormat; GLenum format, type; Uint8 *src, *dst, *tmp; int w, h, length, rows; GL_ActivateRenderer(renderer); if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) { /* FIXME: Do a temp copy to a format that is supported */ SDL_SetError("Unsupported pixel format"); return -1; } SDL_GetWindowSize(window, &w, &h); data->glPixelStorei(GL_PACK_ALIGNMENT, 1); data->glPixelStorei(GL_PACK_ROW_LENGTH, (pitch / SDL_BYTESPERPIXEL(pixel_format))); data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h, format, type, pixels); /* Flip the rows to be top-down */ length = rect->w * SDL_BYTESPERPIXEL(pixel_format); src = (Uint8*)pixels + (rect->h-1)*pitch; dst = (Uint8*)pixels; tmp = SDL_stack_alloc(Uint8, length); rows = rect->h / 2; while (rows--) { SDL_memcpy(tmp, dst, length); SDL_memcpy(dst, src, length); SDL_memcpy(src, tmp, length); dst += pitch; src -= pitch; } SDL_stack_free(tmp); return 0; }
/* This is called if we need to invalidate all of the SDL OpenGL state */ static void GL_ResetState(SDL_Renderer *renderer) { GL_RenderData *data = (GL_RenderData *) renderer->driverdata; if (SDL_CurrentContext == data->context) { GL_UpdateViewport(renderer); } else { GL_ActivateRenderer(renderer); } data->current.shader = SHADER_NONE; data->current.color = 0; data->current.blendMode = -1; data->glDisable(GL_DEPTH_TEST); data->glDisable(GL_CULL_FACE); /* This ended up causing video discrepancies between OpenGL and Direct3D */ /*data->glEnable(GL_LINE_SMOOTH);*/ data->glMatrixMode(GL_MODELVIEW); data->glLoadIdentity(); }
static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) { GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; GL_TextureData *data = (GL_TextureData *) texture->driverdata; GL_ActivateRenderer(renderer); if (!data) { return; } if (data->texture) { renderdata->glDeleteTextures(1, &data->texture); } if (data->yuv) { renderdata->glDeleteTextures(1, &data->utexture); renderdata->glDeleteTextures(1, &data->vtexture); } if (data->pixels) { SDL_free(data->pixels); } SDL_free(data); texture->driverdata = NULL; }
static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect) { GL_RenderData *data = (GL_RenderData *) renderer->driverdata; GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata; int minx, miny, maxx, maxy; GLfloat minu, maxu, minv, maxv; GL_ActivateRenderer(renderer); data->glEnable(texturedata->type); if (texturedata->yuv) { data->glActiveTextureARB(GL_TEXTURE2_ARB); data->glBindTexture(texturedata->type, texturedata->vtexture); if (texturedata->scaleMode != data->current.scaleMode) { data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, texturedata->scaleMode); data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, texturedata->scaleMode); } data->glActiveTextureARB(GL_TEXTURE1_ARB); data->glBindTexture(texturedata->type, texturedata->utexture); if (texturedata->scaleMode != data->current.scaleMode) { data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, texturedata->scaleMode); data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, texturedata->scaleMode); } data->glActiveTextureARB(GL_TEXTURE0_ARB); } data->glBindTexture(texturedata->type, texturedata->texture); if (texturedata->scaleMode != data->current.scaleMode) { data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, texturedata->scaleMode); data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, texturedata->scaleMode); data->current.scaleMode = texturedata->scaleMode; } if (texture->modMode) { GL_SetColor(data, texture->r, texture->g, texture->b, texture->a); } else { GL_SetColor(data, 255, 255, 255, 255); } GL_SetBlendMode(data, texture->blendMode); if (texturedata->yuv) { GL_SetShader(data, SHADER_YV12); } else { GL_SetShader(data, SHADER_RGB); } 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; data->glBegin(GL_TRIANGLE_STRIP); data->glTexCoord2f(minu, minv); data->glVertex2f((GLfloat) minx, (GLfloat) miny); data->glTexCoord2f(maxu, minv); data->glVertex2f((GLfloat) maxx, (GLfloat) miny); data->glTexCoord2f(minu, maxv); data->glVertex2f((GLfloat) minx, (GLfloat) maxy); data->glTexCoord2f(maxu, maxv); data->glVertex2f((GLfloat) maxx, (GLfloat) maxy); data->glEnd(); data->glDisable(texturedata->type); return 0; }
static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; GL_TextureData *data; GLint internalFormat; GLenum format, type; int texture_w, texture_h; GLenum result; GL_ActivateRenderer(renderer); if (!convert_format(renderdata, texture->format, &internalFormat, &format, &type)) { SDL_SetError("Texture format %s not supported by OpenGL", SDL_GetPixelFormatName(texture->format)); return -1; } data = (GL_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } if (texture->access == SDL_TEXTUREACCESS_STREAMING) { size_t size; data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); size = texture->h * data->pitch; if (texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { /* Need to add size for the U and V planes */ size += (2 * (texture->h * data->pitch) / 4); } data->pixels = SDL_malloc(size); if (!data->pixels) { SDL_OutOfMemory(); SDL_free(data); return -1; } } texture->driverdata = data; renderdata->glGetError(); renderdata->glGenTextures(1, &data->texture); if (renderdata->GL_ARB_texture_rectangle_supported) { data->type = GL_TEXTURE_RECTANGLE_ARB; texture_w = texture->w; texture_h = texture->h; data->texw = (GLfloat) texture_w; data->texh = (GLfloat) texture_h; } else { data->type = GL_TEXTURE_2D; 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; data->scaleMode = GL_LINEAR; renderdata->glEnable(data->type); renderdata->glBindTexture(data->type, data->texture); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #ifdef __MACOSX__ #ifndef GL_TEXTURE_STORAGE_HINT_APPLE #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC #endif #ifndef STORAGE_CACHED_APPLE #define STORAGE_CACHED_APPLE 0x85BE #endif #ifndef STORAGE_SHARED_APPLE #define STORAGE_SHARED_APPLE 0x85BF #endif if (texture->access == SDL_TEXTUREACCESS_STREAMING) { renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); } else { renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); } if (texture->access == SDL_TEXTUREACCESS_STREAMING && texture->format == SDL_PIXELFORMAT_ARGB8888) { renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0, format, type, data->pixels); } else #endif { renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0, format, type, NULL); } renderdata->glDisable(data->type); result = renderdata->glGetError(); if (result != GL_NO_ERROR) { GL_SetError("glTexImage2D()", result); return -1; } if (texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { data->yuv = SDL_TRUE; renderdata->glGenTextures(1, &data->utexture); renderdata->glGenTextures(1, &data->vtexture); renderdata->glEnable(data->type); renderdata->glBindTexture(data->type, data->utexture); 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/2, texture_h/2, 0, format, type, NULL); renderdata->glBindTexture(data->type, data->vtexture); 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/2, texture_h/2, 0, format, type, NULL); renderdata->glDisable(data->type); } return 0; }