Implementation of render targets, by Mason Wheeler and Gabriel Jacobo
Thanks guys!
This commit is contained in:
parent
2e70e7f3cb
commit
a49a88676f
11 changed files with 879 additions and 45 deletions
|
@ -88,7 +88,8 @@ typedef struct SDL_RendererInfo
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SDL_TEXTUREACCESS_STATIC, /**< Changes rarely, not lockable */
|
SDL_TEXTUREACCESS_STATIC, /**< Changes rarely, not lockable */
|
||||||
SDL_TEXTUREACCESS_STREAMING /**< Changes frequently, lockable */
|
SDL_TEXTUREACCESS_STREAMING, /**< Changes frequently, lockable */
|
||||||
|
SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */
|
||||||
} SDL_TextureAccess;
|
} SDL_TextureAccess;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -561,6 +562,31 @@ extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
|
||||||
const SDL_Rect * srcrect,
|
const SDL_Rect * srcrect,
|
||||||
const SDL_Rect * dstrect);
|
const SDL_Rect * dstrect);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn SDL_bool SDL_RenderTargetSupported(SDL_Renderer *renderer)
|
||||||
|
*
|
||||||
|
* \brief Determines whether a window supports the use of render targets
|
||||||
|
*
|
||||||
|
* \param renderer The renderer that will be checked
|
||||||
|
*
|
||||||
|
* \return SDL_TRUE if supported, SDL_FALSE if not.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_bool SDLCALL SDL_RenderTargetSupported(SDL_Renderer *renderer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn int SDL_SetTargetTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
|
*
|
||||||
|
* \brief Set a texture as the current rendering target.
|
||||||
|
*
|
||||||
|
* \param renderer The renderer that will be checked
|
||||||
|
*
|
||||||
|
* \param texture The targeted texture, or NULL for the default render target
|
||||||
|
*
|
||||||
|
* \return 0 on success, or -1 if there is no rendering context current, or the driver doesn't support the requested operation.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL SDL_SetTargetTexture(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read pixels from the current rendering target.
|
* \brief Read pixels from the current rendering target.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1014,9 +1014,9 @@ int
|
||||||
SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
|
SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
|
||||||
{
|
{
|
||||||
SDL_Rect full_rect;
|
SDL_Rect full_rect;
|
||||||
|
|
||||||
CHECK_RENDERER_MAGIC(renderer, -1);
|
CHECK_RENDERER_MAGIC(renderer, -1);
|
||||||
|
|
||||||
/* If 'rect' == NULL, then outline the whole surface */
|
/* If 'rect' == NULL, then outline the whole surface */
|
||||||
if (!rect) {
|
if (!rect) {
|
||||||
full_rect.x = 0;
|
full_rect.x = 0;
|
||||||
|
@ -1150,6 +1150,35 @@ SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
format, pixels, pitch);
|
format, pixels, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
SDL_RenderTargetSupported(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
if ((!renderer) || (!renderer->SetTargetTexture)) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_SetTargetTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!renderer) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!renderer->SetTargetTexture) {
|
||||||
|
SDL_Unsupported();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Warning: texture==NULL is a valid parameter
|
||||||
|
if( texture ) {
|
||||||
|
CHECK_TEXTURE_MAGIC(texture, -1);
|
||||||
|
if(renderer != texture->renderer) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderer->SetTargetTexture(renderer, texture);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SDL_RenderPresent(SDL_Renderer * renderer)
|
SDL_RenderPresent(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,6 +87,7 @@ struct SDL_Renderer
|
||||||
int count);
|
int count);
|
||||||
int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
|
int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
||||||
|
int (*SetTargetTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
|
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch);
|
Uint32 format, void * pixels, int pitch);
|
||||||
void (*RenderPresent) (SDL_Renderer * renderer);
|
void (*RenderPresent) (SDL_Renderer * renderer);
|
||||||
|
|
|
@ -111,6 +111,7 @@ static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
||||||
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 format, void * pixels, int pitch);
|
Uint32 format, void * pixels, int pitch);
|
||||||
|
static int D3D_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
static void D3D_RenderPresent(SDL_Renderer * renderer);
|
static void D3D_RenderPresent(SDL_Renderer * renderer);
|
||||||
static void D3D_DestroyTexture(SDL_Renderer * renderer,
|
static void D3D_DestroyTexture(SDL_Renderer * renderer,
|
||||||
SDL_Texture * texture);
|
SDL_Texture * texture);
|
||||||
|
@ -138,6 +139,12 @@ typedef struct
|
||||||
SDL_bool updateSize;
|
SDL_bool updateSize;
|
||||||
SDL_bool beginScene;
|
SDL_bool beginScene;
|
||||||
D3DTEXTUREFILTERTYPE scaleMode;
|
D3DTEXTUREFILTERTYPE scaleMode;
|
||||||
|
IDirect3DSurface9 *defaultRenderTarget;
|
||||||
|
IDirect3DSurface9 *currentRenderTarget;
|
||||||
|
SDL_bool renderTargetActive;
|
||||||
|
SDL_Rect viewport_copy;
|
||||||
|
|
||||||
|
Uint32 NumSimultaneousRTs;
|
||||||
} D3D_RenderData;
|
} D3D_RenderData;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -392,6 +399,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->RenderFillRects = D3D_RenderFillRects;
|
renderer->RenderFillRects = D3D_RenderFillRects;
|
||||||
renderer->RenderCopy = D3D_RenderCopy;
|
renderer->RenderCopy = D3D_RenderCopy;
|
||||||
renderer->RenderReadPixels = D3D_RenderReadPixels;
|
renderer->RenderReadPixels = D3D_RenderReadPixels;
|
||||||
|
renderer->SetTargetTexture = D3D_SetTargetTexture;
|
||||||
renderer->RenderPresent = D3D_RenderPresent;
|
renderer->RenderPresent = D3D_RenderPresent;
|
||||||
renderer->DestroyTexture = D3D_DestroyTexture;
|
renderer->DestroyTexture = D3D_DestroyTexture;
|
||||||
renderer->DestroyRenderer = D3D_DestroyRenderer;
|
renderer->DestroyRenderer = D3D_DestroyRenderer;
|
||||||
|
@ -478,6 +486,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
|
IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
|
||||||
renderer->info.max_texture_width = caps.MaxTextureWidth;
|
renderer->info.max_texture_width = caps.MaxTextureWidth;
|
||||||
renderer->info.max_texture_height = caps.MaxTextureHeight;
|
renderer->info.max_texture_height = caps.MaxTextureHeight;
|
||||||
|
data->NumSimultaneousRTs = caps.NumSimultaneousRTs;
|
||||||
|
|
||||||
/* Set up parameters for rendering */
|
/* Set up parameters for rendering */
|
||||||
IDirect3DDevice9_SetVertexShader(data->device, NULL);
|
IDirect3DDevice9_SetVertexShader(data->device, NULL);
|
||||||
|
@ -507,6 +516,11 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
|
IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
|
||||||
D3DTOP_DISABLE);
|
D3DTOP_DISABLE);
|
||||||
|
|
||||||
|
/* Store the default render target */
|
||||||
|
IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget );
|
||||||
|
data->currentRenderTarget = NULL;
|
||||||
|
data->renderTargetActive = SDL_FALSE;
|
||||||
|
|
||||||
/* Set an identity world and view matrix */
|
/* Set an identity world and view matrix */
|
||||||
matrix.m[0][0] = 1.0f;
|
matrix.m[0][0] = 1.0f;
|
||||||
matrix.m[0][1] = 0.0f;
|
matrix.m[0][1] = 0.0f;
|
||||||
|
@ -554,6 +568,80 @@ GetScaleQuality(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
D3D_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
|
{
|
||||||
|
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
|
||||||
|
D3D_TextureData *texturedata;
|
||||||
|
HRESULT result;
|
||||||
|
|
||||||
|
if (!renderer) return -1;
|
||||||
|
D3D_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
if (data->NumSimultaneousRTs < 2) {
|
||||||
|
SDL_Unsupported();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the previous render target if it wasn't the default one
|
||||||
|
if (data->currentRenderTarget != NULL) {
|
||||||
|
IDirect3DSurface9_Release(data->currentRenderTarget);
|
||||||
|
data->currentRenderTarget = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare an identity world and view matrix */
|
||||||
|
D3DMATRIX matrix;
|
||||||
|
matrix.m[0][0] = 1.0f;
|
||||||
|
matrix.m[0][1] = 0.0f;
|
||||||
|
matrix.m[0][2] = 0.0f;
|
||||||
|
matrix.m[0][3] = 0.0f;
|
||||||
|
matrix.m[1][0] = 0.0f;
|
||||||
|
matrix.m[1][1] = 1.0f;
|
||||||
|
matrix.m[1][2] = 0.0f;
|
||||||
|
matrix.m[1][3] = 0.0f;
|
||||||
|
matrix.m[2][0] = 0.0f;
|
||||||
|
matrix.m[2][1] = 0.0f;
|
||||||
|
matrix.m[2][2] = 1.0f;
|
||||||
|
matrix.m[2][3] = 0.0f;
|
||||||
|
matrix.m[3][0] = 0.0f;
|
||||||
|
matrix.m[3][1] = 0.0f;
|
||||||
|
matrix.m[3][2] = 0.0f;
|
||||||
|
matrix.m[3][3] = 1.0f;
|
||||||
|
|
||||||
|
if (texture == NULL) {
|
||||||
|
if (data->renderTargetActive) {
|
||||||
|
data->renderTargetActive = SDL_FALSE;
|
||||||
|
IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget );
|
||||||
|
renderer->viewport = data->viewport_copy;
|
||||||
|
D3D_UpdateViewport(renderer);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (renderer != texture->renderer) return -1;
|
||||||
|
|
||||||
|
if ( !data->renderTargetActive ) {
|
||||||
|
data->viewport_copy = renderer->viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
texturedata = (D3D_TextureData *) texture->driverdata;
|
||||||
|
result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture, 0, &data->currentRenderTarget );
|
||||||
|
if(FAILED(result)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget );
|
||||||
|
if(FAILED(result)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->renderTargetActive = SDL_TRUE;
|
||||||
|
renderer->viewport.x = 0;
|
||||||
|
renderer->viewport.y = 0;
|
||||||
|
renderer->viewport.w = texture->w;
|
||||||
|
renderer->viewport.h = texture->h;
|
||||||
|
D3D_UpdateViewport(renderer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
{
|
{
|
||||||
|
@ -580,6 +668,11 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
usage = D3DUSAGE_DYNAMIC;
|
usage = D3DUSAGE_DYNAMIC;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
|
||||||
|
pool = D3DPOOL_DEFAULT; // D3DPOOL_MANAGED does not work with usage=D3DUSAGE_RENDERTARGET
|
||||||
|
usage = D3DUSAGE_RENDERTARGET;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
pool = D3DPOOL_MANAGED;
|
pool = D3DPOOL_MANAGED;
|
||||||
usage = 0;
|
usage = 0;
|
||||||
|
@ -1187,6 +1280,13 @@ D3D_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
|
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
|
// Release the render target
|
||||||
|
IDirect3DSurface9_Release(data->defaultRenderTarget);
|
||||||
|
if (data->currentRenderTarget != NULL) {
|
||||||
|
IDirect3DSurface9_Release(data->currentRenderTarget);
|
||||||
|
data->currentRenderTarget = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (data->device) {
|
if (data->device) {
|
||||||
IDirect3DDevice9_Release(data->device);
|
IDirect3DDevice9_Release(data->device);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
const SDL_Rect * srcrect, const SDL_Rect * dstrect);
|
||||||
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 pixel_format, void * pixels, int pitch);
|
Uint32 pixel_format, void * pixels, int pitch);
|
||||||
|
static int GL_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
static void GL_RenderPresent(SDL_Renderer * renderer);
|
static void GL_RenderPresent(SDL_Renderer * renderer);
|
||||||
static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
static void GL_DestroyRenderer(SDL_Renderer * renderer);
|
static void GL_DestroyRenderer(SDL_Renderer * renderer);
|
||||||
|
@ -82,6 +83,15 @@ SDL_RenderDriver GL_RenderDriver = {
|
||||||
0}
|
0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct GL_FBOList GL_FBOList;
|
||||||
|
|
||||||
|
struct GL_FBOList
|
||||||
|
{
|
||||||
|
Uint32 w, h;
|
||||||
|
GLuint FBO;
|
||||||
|
GL_FBOList *next;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SDL_GLContext context;
|
SDL_GLContext context;
|
||||||
|
@ -91,6 +101,11 @@ typedef struct
|
||||||
Uint32 color;
|
Uint32 color;
|
||||||
int blendMode;
|
int blendMode;
|
||||||
} current;
|
} current;
|
||||||
|
|
||||||
|
SDL_bool GL_EXT_framebuffer_object_supported;
|
||||||
|
GL_FBOList *framebuffers;
|
||||||
|
SDL_Texture *renderTarget;
|
||||||
|
SDL_Rect viewport_copy;
|
||||||
|
|
||||||
/* OpenGL functions */
|
/* OpenGL functions */
|
||||||
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
|
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
|
||||||
|
@ -101,6 +116,12 @@ typedef struct
|
||||||
SDL_bool GL_ARB_multitexture_supported;
|
SDL_bool GL_ARB_multitexture_supported;
|
||||||
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
|
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
|
||||||
GLint num_texture_units;
|
GLint num_texture_units;
|
||||||
|
|
||||||
|
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
|
||||||
|
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
|
||||||
|
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
|
||||||
|
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
|
||||||
|
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
|
||||||
|
|
||||||
/* Shader support */
|
/* Shader support */
|
||||||
GL_ShaderContext *shaders;
|
GL_ShaderContext *shaders;
|
||||||
|
@ -123,6 +144,8 @@ typedef struct
|
||||||
SDL_bool yuv;
|
SDL_bool yuv;
|
||||||
GLuint utexture;
|
GLuint utexture;
|
||||||
GLuint vtexture;
|
GLuint vtexture;
|
||||||
|
|
||||||
|
GL_FBOList *fbo;
|
||||||
} GL_TextureData;
|
} GL_TextureData;
|
||||||
|
|
||||||
|
|
||||||
|
@ -227,6 +250,29 @@ GL_ResetState(SDL_Renderer *renderer)
|
||||||
data->glLoadIdentity();
|
data->glLoadIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GL_FBOList *
|
||||||
|
GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
|
||||||
|
{
|
||||||
|
GL_FBOList *result = data->framebuffers;
|
||||||
|
|
||||||
|
while (result && ((result->w != w) || (result->h != h))) {
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
result = SDL_malloc(sizeof(GL_FBOList));
|
||||||
|
if (result) {
|
||||||
|
result->w = w;
|
||||||
|
result->h = h;
|
||||||
|
data->glGenFramebuffersEXT(1, &result->FBO);
|
||||||
|
result->next = data->framebuffers;
|
||||||
|
data->framebuffers = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Renderer *
|
SDL_Renderer *
|
||||||
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
{
|
{
|
||||||
|
@ -269,6 +315,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->RenderDrawLines = GL_RenderDrawLines;
|
renderer->RenderDrawLines = GL_RenderDrawLines;
|
||||||
renderer->RenderFillRects = GL_RenderFillRects;
|
renderer->RenderFillRects = GL_RenderFillRects;
|
||||||
renderer->RenderCopy = GL_RenderCopy;
|
renderer->RenderCopy = GL_RenderCopy;
|
||||||
|
renderer->SetTargetTexture = GL_SetTargetTexture;
|
||||||
renderer->RenderReadPixels = GL_RenderReadPixels;
|
renderer->RenderReadPixels = GL_RenderReadPixels;
|
||||||
renderer->RenderPresent = GL_RenderPresent;
|
renderer->RenderPresent = GL_RenderPresent;
|
||||||
renderer->DestroyTexture = GL_DestroyTexture;
|
renderer->DestroyTexture = GL_DestroyTexture;
|
||||||
|
@ -341,6 +388,22 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
|
||||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SDL_GL_ExtensionSupported("GL_EXT_framebuffer_object")) {
|
||||||
|
data->GL_EXT_framebuffer_object_supported = SDL_TRUE;
|
||||||
|
data->glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)
|
||||||
|
SDL_GL_GetProcAddress("glGenFramebuffersEXT");
|
||||||
|
data->glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
|
||||||
|
SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
|
||||||
|
data->glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
|
||||||
|
SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
|
||||||
|
data->glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)
|
||||||
|
SDL_GL_GetProcAddress("glBindFramebufferEXT");
|
||||||
|
data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
|
||||||
|
SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
|
||||||
|
}
|
||||||
|
data->framebuffers = NULL;
|
||||||
|
data->renderTarget = NULL;
|
||||||
|
|
||||||
/* Set up parameters for rendering */
|
/* Set up parameters for rendering */
|
||||||
GL_ResetState(renderer);
|
GL_ResetState(renderer);
|
||||||
|
@ -402,6 +465,74 @@ GetScaleQuality(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GL_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
|
{
|
||||||
|
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
||||||
|
|
||||||
|
GL_TextureData *texturedata;
|
||||||
|
GLenum status;
|
||||||
|
|
||||||
|
if (!renderer) return -1;
|
||||||
|
GL_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
if (! data->GL_EXT_framebuffer_object_supported) {
|
||||||
|
SDL_Unsupported();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture == NULL) {
|
||||||
|
if (data->renderTarget != NULL) {
|
||||||
|
data->renderTarget = NULL;
|
||||||
|
renderer->viewport = data->viewport_copy;
|
||||||
|
data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
data->glMatrixMode(GL_PROJECTION);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glMatrixMode(GL_MODELVIEW);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glViewport(renderer->viewport.x, renderer->viewport.y, renderer->viewport.w, renderer->viewport.h);
|
||||||
|
data->glOrtho(0.0, (GLdouble) renderer->viewport.w, (GLdouble) renderer->viewport.h, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (renderer != texture->renderer) return -1;
|
||||||
|
if (data->renderTarget==NULL) {
|
||||||
|
// Keep a copy of the default viewport to restore when texture==NULL
|
||||||
|
data->viewport_copy = renderer->viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
texturedata = (GL_TextureData *) texture->driverdata;
|
||||||
|
if (!texturedata) {
|
||||||
|
if (texture->native && texture->native->driverdata) {
|
||||||
|
texture = texture->native;
|
||||||
|
texturedata = texture->driverdata;
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texturedata->fbo->FBO);
|
||||||
|
/* TODO: check if texture pixel format allows this operation */
|
||||||
|
data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texturedata->type, texturedata->texture, 0);
|
||||||
|
/* Check FBO status */
|
||||||
|
status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||||
|
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->renderTarget = texture;
|
||||||
|
renderer->viewport.x = 0;
|
||||||
|
renderer->viewport.y = 0;
|
||||||
|
renderer->viewport.w = texture->w;
|
||||||
|
renderer->viewport.h = texture->h;
|
||||||
|
data->glMatrixMode(GL_PROJECTION);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glOrtho(0.0, (GLdouble) texture->w, 0.0, (GLdouble) texture->h, 0.0, 1.0);
|
||||||
|
data->glMatrixMode(GL_MODELVIEW);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glViewport(0, 0, texture->w, texture->h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
{
|
{
|
||||||
|
@ -446,10 +577,17 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->driverdata = data;
|
texture->driverdata = data;
|
||||||
|
|
||||||
|
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
|
||||||
|
data->fbo = GL_GetFBO(renderdata, texture->w, texture->h);
|
||||||
|
} else {
|
||||||
|
data->fbo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
renderdata->glGetError();
|
renderdata->glGetError();
|
||||||
renderdata->glGenTextures(1, &data->texture);
|
renderdata->glGenTextures(1, &data->texture);
|
||||||
if (renderdata->GL_ARB_texture_rectangle_supported) {
|
if ((renderdata->GL_ARB_texture_rectangle_supported)
|
||||||
|
/*&& texture->access != SDL_TEXTUREACCESS_TARGET*/){
|
||||||
data->type = GL_TEXTURE_RECTANGLE_ARB;
|
data->type = GL_TEXTURE_RECTANGLE_ARB;
|
||||||
texture_w = texture->w;
|
texture_w = texture->w;
|
||||||
texture_h = texture->h;
|
texture_h = texture->h;
|
||||||
|
@ -1013,6 +1151,13 @@ GL_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
GL_DestroyShaderContext(data->shaders);
|
GL_DestroyShaderContext(data->shaders);
|
||||||
}
|
}
|
||||||
if (data->context) {
|
if (data->context) {
|
||||||
|
while (data->framebuffers) {
|
||||||
|
GL_FBOList *nextnode = data->framebuffers->next;
|
||||||
|
/* delete the framebuffer object */
|
||||||
|
data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO);
|
||||||
|
SDL_free(data->framebuffers);
|
||||||
|
data->framebuffers = nextnode;
|
||||||
|
}
|
||||||
/* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
|
/* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
|
||||||
SDL_GL_DeleteContext(data->context);
|
SDL_GL_DeleteContext(data->context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,5 +27,13 @@ SDL_PROC(void, glTexParameteriv, (GLenum, GLenum, const GLint *))
|
||||||
SDL_PROC(void, glTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *))
|
SDL_PROC(void, glTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *))
|
||||||
SDL_PROC(void, glVertexPointer, (GLint, GLenum, GLsizei, const GLvoid *))
|
SDL_PROC(void, glVertexPointer, (GLint, GLenum, GLsizei, const GLvoid *))
|
||||||
SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
|
SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
|
||||||
|
SDL_PROC(void, glBindFramebufferOES, (GLenum, GLuint))
|
||||||
|
SDL_PROC(void, glFramebufferTexture2DOES, (GLenum, GLenum, GLenum, GLuint, GLint))
|
||||||
|
SDL_PROC(GLenum, glCheckFramebufferStatusOES, (GLenum))
|
||||||
|
SDL_PROC(void, glPushMatrix, (void))
|
||||||
|
SDL_PROC(void, glTranslatef, (GLfloat, GLfloat, GLfloat))
|
||||||
|
SDL_PROC(void, glRotatef, (GLfloat, GLfloat, GLfloat, GLfloat))
|
||||||
|
SDL_PROC(void, glPopMatrix, (void))
|
||||||
|
SDL_PROC(void, glDeleteFramebuffersOES, (GLsizei, const GLuint*))
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -73,6 +73,16 @@ static void GLES_RenderPresent(SDL_Renderer * renderer);
|
||||||
static void GLES_DestroyTexture(SDL_Renderer * renderer,
|
static void GLES_DestroyTexture(SDL_Renderer * renderer,
|
||||||
SDL_Texture * texture);
|
SDL_Texture * texture);
|
||||||
static void GLES_DestroyRenderer(SDL_Renderer * renderer);
|
static void GLES_DestroyRenderer(SDL_Renderer * renderer);
|
||||||
|
static int GLES_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
|
|
||||||
|
typedef struct GLES_FBOList GLES_FBOList;
|
||||||
|
|
||||||
|
struct GLES_FBOList
|
||||||
|
{
|
||||||
|
Uint32 w, h;
|
||||||
|
GLuint FBO;
|
||||||
|
GLES_FBOList *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
SDL_RenderDriver GLES_RenderDriver = {
|
SDL_RenderDriver GLES_RenderDriver = {
|
||||||
|
@ -98,6 +108,10 @@ typedef struct
|
||||||
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
|
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
|
||||||
#include "SDL_glesfuncs.h"
|
#include "SDL_glesfuncs.h"
|
||||||
#undef SDL_PROC
|
#undef SDL_PROC
|
||||||
|
SDL_bool GL_OES_framebuffer_object_supported;
|
||||||
|
GLES_FBOList *framebuffers;
|
||||||
|
SDL_Texture *renderTarget;
|
||||||
|
SDL_Rect viewport_copy;
|
||||||
|
|
||||||
SDL_bool useDrawTexture;
|
SDL_bool useDrawTexture;
|
||||||
SDL_bool GL_OES_draw_texture_supported;
|
SDL_bool GL_OES_draw_texture_supported;
|
||||||
|
@ -113,6 +127,7 @@ typedef struct
|
||||||
GLenum formattype;
|
GLenum formattype;
|
||||||
void *pixels;
|
void *pixels;
|
||||||
int pitch;
|
int pitch;
|
||||||
|
GLES_FBOList *fbo;
|
||||||
} GLES_TextureData;
|
} GLES_TextureData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -179,6 +194,27 @@ static int GLES_LoadFunctions(GLES_RenderData * data)
|
||||||
|
|
||||||
static SDL_GLContext SDL_CurrentContext = NULL;
|
static SDL_GLContext SDL_CurrentContext = NULL;
|
||||||
|
|
||||||
|
GLES_FBOList *
|
||||||
|
GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h)
|
||||||
|
{
|
||||||
|
GLES_FBOList *result = data->framebuffers;
|
||||||
|
while ((result) && ((result->w != w) || (result->h != h)) )
|
||||||
|
{
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
result = SDL_malloc(sizeof(GLES_FBOList));
|
||||||
|
result->w = w;
|
||||||
|
result->h = h;
|
||||||
|
glGenFramebuffersOES(1, &result->FBO);
|
||||||
|
result->next = data->framebuffers;
|
||||||
|
data->framebuffers = result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GLES_ActivateRenderer(SDL_Renderer * renderer)
|
GLES_ActivateRenderer(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
@ -221,6 +257,71 @@ GLES_ResetState(SDL_Renderer *renderer)
|
||||||
data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
|
{
|
||||||
|
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
|
||||||
|
int w, h;
|
||||||
|
GLES_TextureData *texturedata = NULL;
|
||||||
|
GLenum status;
|
||||||
|
|
||||||
|
if (!renderer) return -1;
|
||||||
|
GLES_ActivateRenderer(renderer);
|
||||||
|
if (! data->GL_OES_framebuffer_object_supported) {
|
||||||
|
SDL_Unsupported();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture == NULL) {
|
||||||
|
if (data->renderTarget != NULL) {
|
||||||
|
data->renderTarget = NULL;
|
||||||
|
renderer->viewport = data->viewport_copy;
|
||||||
|
data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
|
||||||
|
data->glMatrixMode(GL_PROJECTION);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glMatrixMode(GL_MODELVIEW);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glViewport(renderer->viewport.x, renderer->viewport.y, renderer->viewport.w, renderer->viewport.h);
|
||||||
|
data->glOrthof(0.0, (GLfloat) renderer->viewport.w, (GLfloat) renderer->viewport.h, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer != texture->renderer) return -1;
|
||||||
|
if (data->renderTarget==NULL) {
|
||||||
|
// Keep a copy of the default viewport to restore when texture==NULL
|
||||||
|
data->viewport_copy = renderer->viewport;
|
||||||
|
}
|
||||||
|
texturedata = (GLES_TextureData *) texture->driverdata;
|
||||||
|
if (!texturedata) {
|
||||||
|
if (texture->native && texture->native->driverdata) {
|
||||||
|
texture = texture->native;
|
||||||
|
texturedata = texture->driverdata;
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
|
||||||
|
/* TODO: check if texture pixel format allows this operation */
|
||||||
|
data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
|
||||||
|
/* Check FBO status */
|
||||||
|
status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
|
||||||
|
if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data->renderTarget = texture;
|
||||||
|
renderer->viewport.x = 0;
|
||||||
|
renderer->viewport.y = 0;
|
||||||
|
renderer->viewport.w = texture->w;
|
||||||
|
renderer->viewport.h = texture->h;
|
||||||
|
data->glMatrixMode(GL_PROJECTION);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glOrthof(0.0, (GLfloat) texture->w, 0.0, (GLfloat) texture->h, 0.0, 1.0);
|
||||||
|
data->glMatrixMode(GL_MODELVIEW);
|
||||||
|
data->glLoadIdentity();
|
||||||
|
data->glViewport(0, 0, texture->w, texture->h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Renderer *
|
SDL_Renderer *
|
||||||
GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
|
GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
{
|
{
|
||||||
|
@ -274,6 +375,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->info.flags = SDL_RENDERER_ACCELERATED;
|
renderer->info.flags = SDL_RENDERER_ACCELERATED;
|
||||||
renderer->driverdata = data;
|
renderer->driverdata = data;
|
||||||
renderer->window = window;
|
renderer->window = window;
|
||||||
|
renderer->SetTargetTexture = GLES_SetTargetTexture;
|
||||||
|
|
||||||
data->context = SDL_GL_CreateContext(window);
|
data->context = SDL_GL_CreateContext(window);
|
||||||
if (!data->context) {
|
if (!data->context) {
|
||||||
|
@ -317,6 +419,12 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
|
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
|
||||||
renderer->info.max_texture_height = value;
|
renderer->info.max_texture_height = value;
|
||||||
|
|
||||||
|
if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object")) {
|
||||||
|
data->GL_OES_framebuffer_object_supported = SDL_TRUE;
|
||||||
|
}
|
||||||
|
data->framebuffers = NULL;
|
||||||
|
data->renderTarget = NULL;
|
||||||
|
|
||||||
/* Set up parameters for rendering */
|
/* Set up parameters for rendering */
|
||||||
GLES_ResetState(renderer);
|
GLES_ResetState(renderer);
|
||||||
|
|
||||||
|
@ -335,7 +443,7 @@ GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
||||||
|
|
||||||
if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
|
if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
|
||||||
/* According to Apple documentation, we need to finish drawing NOW! */
|
/* According to Apple documentation, we need to finish drawing NOW! */
|
||||||
data->glFinish();
|
data->glFinish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,6 +511,11 @@ GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->driverdata = data;
|
texture->driverdata = data;
|
||||||
|
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
|
||||||
|
data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h);
|
||||||
|
} else {
|
||||||
|
data->fbo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
renderdata->glGetError();
|
renderdata->glGetError();
|
||||||
renderdata->glEnable(GL_TEXTURE_2D);
|
renderdata->glEnable(GL_TEXTURE_2D);
|
||||||
|
@ -757,15 +870,26 @@ GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
SDL_Window *window = renderer->window;
|
SDL_Window *window = renderer->window;
|
||||||
|
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
cropRect[0] = srcrect->x;
|
if (data->renderTarget != NULL) {
|
||||||
cropRect[1] = srcrect->y + srcrect->h;
|
cropRect[0] = srcrect->x;
|
||||||
cropRect[2] = srcrect->w;
|
cropRect[1] = srcrect->y;
|
||||||
cropRect[3] = -srcrect->h;
|
cropRect[2] = srcrect->w;
|
||||||
data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
|
cropRect[3] = srcrect->h;
|
||||||
cropRect);
|
data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
|
||||||
data->glDrawTexiOES(renderer->viewport.x + dstrect->x,
|
cropRect);
|
||||||
h - (renderer->viewport.y + dstrect->y) - dstrect->h, 0,
|
data->glDrawTexiOES(renderer->viewport.x + dstrect->x, renderer->viewport.y + dstrect->y, 0,
|
||||||
dstrect->w, dstrect->h);
|
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 {
|
} else {
|
||||||
|
|
||||||
minx = dstrect->x;
|
minx = dstrect->x;
|
||||||
|
@ -901,6 +1025,12 @@ GLES_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data->context) {
|
if (data->context) {
|
||||||
|
while (data->framebuffers) {
|
||||||
|
GLES_FBOList *nextnode = data->framebuffers->next;
|
||||||
|
data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
|
||||||
|
SDL_free(data->framebuffers);
|
||||||
|
data->framebuffers = nextnode;
|
||||||
|
}
|
||||||
SDL_GL_DeleteContext(data->context);
|
SDL_GL_DeleteContext(data->context);
|
||||||
}
|
}
|
||||||
SDL_free(data);
|
SDL_free(data);
|
||||||
|
|
|
@ -40,3 +40,7 @@ SDL_PROC(void, glUniformMatrix4fv, (GLint, GLsizei, GLboolean, const GLfloat *))
|
||||||
SDL_PROC(void, glUseProgram, (GLuint))
|
SDL_PROC(void, glUseProgram, (GLuint))
|
||||||
SDL_PROC(void, glVertexAttribPointer, (GLuint, GLint, GLenum, GLboolean, GLsizei, const void *))
|
SDL_PROC(void, glVertexAttribPointer, (GLuint, GLint, GLenum, GLboolean, GLsizei, const void *))
|
||||||
SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
|
SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
|
||||||
|
SDL_PROC(void, glBindFramebuffer, (GLenum, GLuint))
|
||||||
|
SDL_PROC(void, glFramebufferTexture2D, (GLenum, GLenum, GLenum, GLuint, GLint))
|
||||||
|
SDL_PROC(GLenum, glCheckFramebufferStatus, (GLenum))
|
||||||
|
SDL_PROC(void, glDeleteFramebuffers, (GLsizei, const GLuint *))
|
||||||
|
|
|
@ -55,6 +55,15 @@ SDL_RenderDriver GLES2_RenderDriver = {
|
||||||
* Context structures *
|
* Context structures *
|
||||||
*************************************************************************************************/
|
*************************************************************************************************/
|
||||||
|
|
||||||
|
typedef struct GLES2_FBOList GLES2_FBOList;
|
||||||
|
|
||||||
|
struct GLES2_FBOList
|
||||||
|
{
|
||||||
|
Uint32 w, h;
|
||||||
|
GLuint FBO;
|
||||||
|
GLES2_FBOList *next;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct GLES2_TextureData
|
typedef struct GLES2_TextureData
|
||||||
{
|
{
|
||||||
GLenum texture;
|
GLenum texture;
|
||||||
|
@ -63,6 +72,7 @@ typedef struct GLES2_TextureData
|
||||||
GLenum pixel_type;
|
GLenum pixel_type;
|
||||||
void *pixel_data;
|
void *pixel_data;
|
||||||
size_t pitch;
|
size_t pitch;
|
||||||
|
GLES2_FBOList *fbo;
|
||||||
} GLES2_TextureData;
|
} GLES2_TextureData;
|
||||||
|
|
||||||
typedef struct GLES2_ShaderCacheEntry
|
typedef struct GLES2_ShaderCacheEntry
|
||||||
|
@ -134,6 +144,9 @@ typedef struct GLES2_DriverContext
|
||||||
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
|
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
|
||||||
#include "SDL_gles2funcs.h"
|
#include "SDL_gles2funcs.h"
|
||||||
#undef SDL_PROC
|
#undef SDL_PROC
|
||||||
|
GLES2_FBOList *framebuffers;
|
||||||
|
SDL_Texture *renderTarget;
|
||||||
|
SDL_Rect viewport_copy;
|
||||||
|
|
||||||
int shader_format_count;
|
int shader_format_count;
|
||||||
GLenum *shader_formats;
|
GLenum *shader_formats;
|
||||||
|
@ -154,6 +167,8 @@ static void GLES2_WindowEvent(SDL_Renderer * renderer,
|
||||||
static int GLES2_UpdateViewport(SDL_Renderer * renderer);
|
static int GLES2_UpdateViewport(SDL_Renderer * renderer);
|
||||||
static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
|
static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
|
||||||
|
|
||||||
|
static int GLES2_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
|
|
||||||
static SDL_GLContext SDL_CurrentContext = NULL;
|
static SDL_GLContext SDL_CurrentContext = NULL;
|
||||||
|
|
||||||
static int GLES2_LoadFunctions(GLES2_DriverContext * data)
|
static int GLES2_LoadFunctions(GLES2_DriverContext * data)
|
||||||
|
@ -176,7 +191,7 @@ static int GLES2_LoadFunctions(GLES2_DriverContext * data)
|
||||||
SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
|
SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
} while ( 0 );
|
} while ( 0 );
|
||||||
#endif /* _SDL_NOGETPROCADDR_ */
|
#endif /* _SDL_NOGETPROCADDR_ */
|
||||||
|
|
||||||
#include "SDL_gles2funcs.h"
|
#include "SDL_gles2funcs.h"
|
||||||
|
@ -184,6 +199,26 @@ static int GLES2_LoadFunctions(GLES2_DriverContext * data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLES2_FBOList *
|
||||||
|
GLES2_GetFBO(GLES2_DriverContext *data, Uint32 w, Uint32 h)
|
||||||
|
{
|
||||||
|
GLES2_FBOList *result = data->framebuffers;
|
||||||
|
while ((result) && ((result->w != w) || (result->h != h)) )
|
||||||
|
{
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
result = SDL_malloc(sizeof(GLES2_FBOList));
|
||||||
|
result->w = w;
|
||||||
|
result->h = h;
|
||||||
|
glGenFramebuffers(1, &result->FBO);
|
||||||
|
result->next = data->framebuffers;
|
||||||
|
data->framebuffers = result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GLES2_ActivateRenderer(SDL_Renderer * renderer)
|
GLES2_ActivateRenderer(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
@ -207,7 +242,7 @@ static void
|
||||||
GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
||||||
{
|
{
|
||||||
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
|
|
||||||
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||||
/* Rebind the context to the window area */
|
/* Rebind the context to the window area */
|
||||||
SDL_CurrentContext = NULL;
|
SDL_CurrentContext = NULL;
|
||||||
|
@ -267,6 +302,12 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rdata->context) {
|
if (rdata->context) {
|
||||||
|
while (rdata->framebuffers) {
|
||||||
|
GLES2_FBOList *nextnode = rdata->framebuffers->next;
|
||||||
|
rdata->glDeleteFramebuffers(1, &rdata->framebuffers->FBO);
|
||||||
|
SDL_free(rdata->framebuffers);
|
||||||
|
rdata->framebuffers = nextnode;
|
||||||
|
}
|
||||||
SDL_GL_DeleteContext(rdata->context);
|
SDL_GL_DeleteContext(rdata->context);
|
||||||
}
|
}
|
||||||
if (rdata->shader_formats) {
|
if (rdata->shader_formats) {
|
||||||
|
@ -371,6 +412,13 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
texture->driverdata = tdata;
|
texture->driverdata = tdata;
|
||||||
|
|
||||||
|
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
|
||||||
|
tdata->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
|
||||||
|
} else {
|
||||||
|
tdata->fbo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +481,7 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
/* Bail out if we're supposed to update an empty rectangle */
|
/* Bail out if we're supposed to update an empty rectangle */
|
||||||
if (rect->w <= 0 || rect->h <= 0)
|
if (rect->w <= 0 || rect->h <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -543,7 +591,7 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
|
||||||
entry->vertex_shader = vertex;
|
entry->vertex_shader = vertex;
|
||||||
entry->fragment_shader = fragment;
|
entry->fragment_shader = fragment;
|
||||||
entry->blend_mode = blendMode;
|
entry->blend_mode = blendMode;
|
||||||
|
|
||||||
/* Create the program and link it */
|
/* Create the program and link it */
|
||||||
rdata->glGetError();
|
rdata->glGetError();
|
||||||
entry->id = rdata->glCreateProgram();
|
entry->id = rdata->glCreateProgram();
|
||||||
|
@ -560,7 +608,7 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
|
||||||
SDL_free(entry);
|
SDL_free(entry);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Predetermine locations of uniform variables */
|
/* Predetermine locations of uniform variables */
|
||||||
entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
|
entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
|
||||||
rdata->glGetUniformLocation(entry->id, "u_projection");
|
rdata->glGetUniformLocation(entry->id, "u_projection");
|
||||||
|
@ -625,7 +673,7 @@ GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode b
|
||||||
SDL_SetError("No shader matching the requested characteristics was found");
|
SDL_SetError("No shader matching the requested characteristics was found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a matching shader instance that's supported on this hardware */
|
/* Find a matching shader instance that's supported on this hardware */
|
||||||
for (i = 0; i < shader->instance_count && !instance; ++i)
|
for (i = 0; i < shader->instance_count && !instance; ++i)
|
||||||
{
|
{
|
||||||
|
@ -872,7 +920,7 @@ GLES2_RenderClear(SDL_Renderer * renderer)
|
||||||
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
rdata->glClearColor((GLfloat) renderer->r * inv255f,
|
rdata->glClearColor((GLfloat) renderer->r * inv255f,
|
||||||
(GLfloat) renderer->g * inv255f,
|
(GLfloat) renderer->g * inv255f,
|
||||||
(GLfloat) renderer->b * inv255f,
|
(GLfloat) renderer->b * inv255f,
|
||||||
|
@ -1080,20 +1128,83 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
|
|
||||||
/* Activate an appropriate shader and set the projection matrix */
|
/* Activate an appropriate shader and set the projection matrix */
|
||||||
blendMode = texture->blendMode;
|
blendMode = texture->blendMode;
|
||||||
switch (texture->format)
|
if (rdata->renderTarget!=NULL) {
|
||||||
{
|
/* Check if we need to do color mapping between the source and render target textures */
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
if (rdata->renderTarget->format != texture->format) {
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
switch (texture->format)
|
||||||
break;
|
{
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
switch (rdata->renderTarget->format)
|
||||||
break;
|
{
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
break;
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
case SDL_PIXELFORMAT_RGB888:
|
break;
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
break;
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
switch (rdata->renderTarget->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
switch (rdata->renderTarget->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
switch (rdata->renderTarget->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; // Texture formats match, use the non color mapping shader (even if the formats are not ABGR)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (texture->format)
|
||||||
|
{
|
||||||
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_RGB888:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
|
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1119,15 +1230,29 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
GLES2_SetTexCoords(rdata, SDL_TRUE);
|
GLES2_SetTexCoords(rdata, SDL_TRUE);
|
||||||
|
|
||||||
/* Emit the textured quad */
|
/* Emit the textured quad */
|
||||||
vertices[0] = (GLfloat)dstrect->x;
|
if (rdata->renderTarget!=NULL) {
|
||||||
vertices[1] = (GLfloat)dstrect->y;
|
// Flip the texture vertically to compensate for the inversion it'll be subjected to later when it's rendered to the screen
|
||||||
vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
|
vertices[0] = (GLfloat)dstrect->x;
|
||||||
vertices[3] = (GLfloat)dstrect->y;
|
vertices[1] = (GLfloat)renderer->viewport.h-dstrect->y;
|
||||||
vertices[4] = (GLfloat)dstrect->x;
|
vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
vertices[5] = (GLfloat)(dstrect->y + dstrect->h);
|
vertices[3] = (GLfloat)renderer->viewport.h-dstrect->y;
|
||||||
vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
|
vertices[4] = (GLfloat)dstrect->x;
|
||||||
vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
|
vertices[5] = (GLfloat)renderer->viewport.h-(dstrect->y + dstrect->h);
|
||||||
|
vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
|
vertices[7] = (GLfloat)renderer->viewport.h-(dstrect->y + dstrect->h);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertices[0] = (GLfloat)dstrect->x;
|
||||||
|
vertices[1] = (GLfloat)dstrect->y;
|
||||||
|
vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
|
vertices[3] = (GLfloat)dstrect->y;
|
||||||
|
vertices[4] = (GLfloat)dstrect->x;
|
||||||
|
vertices[5] = (GLfloat)(dstrect->y + dstrect->h);
|
||||||
|
vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
|
||||||
|
vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
|
||||||
|
}
|
||||||
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
|
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||||
|
|
||||||
texCoords[0] = srcrect->x / (GLfloat)texture->w;
|
texCoords[0] = srcrect->x / (GLfloat)texture->w;
|
||||||
texCoords[1] = srcrect->y / (GLfloat)texture->h;
|
texCoords[1] = srcrect->y / (GLfloat)texture->h;
|
||||||
texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
|
||||||
|
@ -1231,6 +1356,60 @@ GLES2_ResetState(SDL_Renderer *renderer)
|
||||||
rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
|
rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES2_SetTargetTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
|
{
|
||||||
|
GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
|
||||||
|
GLES2_TextureData *texturedata = NULL;
|
||||||
|
GLenum status;
|
||||||
|
SDL_BlendMode blendMode;
|
||||||
|
|
||||||
|
if (!renderer) return -1;
|
||||||
|
|
||||||
|
blendMode = texture->blendMode;
|
||||||
|
if (texture == NULL) {
|
||||||
|
if (data->renderTarget!=NULL) {
|
||||||
|
data->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
renderer->viewport = data->viewport_copy;
|
||||||
|
data->renderTarget = NULL;
|
||||||
|
data->glViewport(renderer->viewport.x, renderer->viewport.y, renderer->viewport.w, renderer->viewport.h);
|
||||||
|
if(data->current_program) GLES2_SetOrthographicProjection(renderer);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (renderer != texture->renderer) return -1;
|
||||||
|
if (data->renderTarget==NULL) {
|
||||||
|
// Keep a copy of the default viewport to restore when texture==NULL
|
||||||
|
data->viewport_copy = renderer->viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
texturedata = (GLES2_TextureData *) texture->driverdata;
|
||||||
|
if (!texturedata) {
|
||||||
|
if (texture->native && texture->native->driverdata) {
|
||||||
|
texture = texture->native;
|
||||||
|
texturedata = texture->driverdata;
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
|
||||||
|
/* TODO: check if texture pixel format allows this operation */
|
||||||
|
data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
|
||||||
|
/* Check FBO status */
|
||||||
|
status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->viewport.x = 0;
|
||||||
|
renderer->viewport.y = 0;
|
||||||
|
renderer->viewport.w = texture->w;
|
||||||
|
renderer->viewport.h = texture->h;
|
||||||
|
data->renderTarget = texture;
|
||||||
|
data->glViewport(0, 0, texture->w, texture->h);
|
||||||
|
if(data->current_program) GLES2_SetOrthographicProjection(renderer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_Renderer *
|
static SDL_Renderer *
|
||||||
GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
{
|
{
|
||||||
|
@ -1241,10 +1420,10 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
GLboolean hasCompiler;
|
GLboolean hasCompiler;
|
||||||
#endif
|
#endif
|
||||||
Uint32 windowFlags;
|
Uint32 windowFlags;
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
|
|
||||||
windowFlags = SDL_GetWindowFlags(window);
|
windowFlags = SDL_GetWindowFlags(window);
|
||||||
if (!(windowFlags & SDL_WINDOW_OPENGL)) {
|
if (!(windowFlags & SDL_WINDOW_OPENGL)) {
|
||||||
if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) {
|
if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) {
|
||||||
|
@ -1331,6 +1510,9 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
rdata->shader_formats[nFormats - 1] = (GLenum)-1;
|
rdata->shader_formats[nFormats - 1] = (GLenum)-1;
|
||||||
#endif /* ZUNE_HD */
|
#endif /* ZUNE_HD */
|
||||||
|
|
||||||
|
rdata->framebuffers = NULL;
|
||||||
|
rdata->renderTarget = NULL;
|
||||||
|
|
||||||
/* Populate the function pointers for the module */
|
/* Populate the function pointers for the module */
|
||||||
renderer->WindowEvent = &GLES2_WindowEvent;
|
renderer->WindowEvent = &GLES2_WindowEvent;
|
||||||
renderer->CreateTexture = &GLES2_CreateTexture;
|
renderer->CreateTexture = &GLES2_CreateTexture;
|
||||||
|
@ -1347,6 +1529,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
renderer->RenderPresent = &GLES2_RenderPresent;
|
renderer->RenderPresent = &GLES2_RenderPresent;
|
||||||
renderer->DestroyTexture = &GLES2_DestroyTexture;
|
renderer->DestroyTexture = &GLES2_DestroyTexture;
|
||||||
renderer->DestroyRenderer = &GLES2_DestroyRenderer;
|
renderer->DestroyRenderer = &GLES2_DestroyRenderer;
|
||||||
|
renderer->SetTargetTexture = &GLES2_SetTargetTexture;
|
||||||
|
|
||||||
GLES2_ResetState(renderer);
|
GLES2_ResetState(renderer);
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ TARGETS = \
|
||||||
testoverlay2$(EXE) \
|
testoverlay2$(EXE) \
|
||||||
testplatform$(EXE) \
|
testplatform$(EXE) \
|
||||||
testpower$(EXE) \
|
testpower$(EXE) \
|
||||||
|
testrendertarget$(EXE) \
|
||||||
testresample$(EXE) \
|
testresample$(EXE) \
|
||||||
testscale$(EXE) \
|
testscale$(EXE) \
|
||||||
testsem$(EXE) \
|
testsem$(EXE) \
|
||||||
|
@ -181,6 +182,9 @@ testplatform$(EXE): $(srcdir)/testplatform.c
|
||||||
testpower$(EXE): $(srcdir)/testpower.c
|
testpower$(EXE): $(srcdir)/testpower.c
|
||||||
$(CC) -o $@ $? $(CFLAGS) $(LIBS)
|
$(CC) -o $@ $? $(CFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
testrendertarget$(EXE): $(srcdir)/testrendertarget.c $(srcdir)/common.c
|
||||||
|
$(CC) -o $@ $(srcdir)/testrendertarget.c $(srcdir)/common.c $(CFLAGS) $(LIBS)
|
||||||
|
|
||||||
testscale$(EXE): $(srcdir)/testscale.c $(srcdir)/common.c
|
testscale$(EXE): $(srcdir)/testscale.c $(srcdir)/common.c
|
||||||
$(CC) -o $@ $(srcdir)/testscale.c $(srcdir)/common.c $(CFLAGS) $(LIBS)
|
$(CC) -o $@ $(srcdir)/testscale.c $(srcdir)/common.c $(CFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
|
204
test/testrendertarget.c
Normal file
204
test/testrendertarget.c
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely.
|
||||||
|
*/
|
||||||
|
/* Simple program: Move N sprites around on the screen as fast as possible */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define WINDOW_WIDTH 640
|
||||||
|
#define WINDOW_HEIGHT 480
|
||||||
|
|
||||||
|
static CommonState *state;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
SDL_Texture *background;
|
||||||
|
SDL_Texture *sprite;
|
||||||
|
SDL_Rect sprite_rect;
|
||||||
|
int scale_direction;
|
||||||
|
} DrawState;
|
||||||
|
|
||||||
|
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
|
||||||
|
static void
|
||||||
|
quit(int rc)
|
||||||
|
{
|
||||||
|
CommonQuit(state);
|
||||||
|
exit(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Texture *
|
||||||
|
LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
|
||||||
|
{
|
||||||
|
SDL_Surface *temp;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
|
||||||
|
/* Load the sprite image */
|
||||||
|
temp = SDL_LoadBMP(file);
|
||||||
|
if (temp == NULL) {
|
||||||
|
fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set transparent pixel as the pixel at (0,0) */
|
||||||
|
if (transparent) {
|
||||||
|
if (temp->format->palette) {
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
|
||||||
|
} else {
|
||||||
|
switch (temp->format->BitsPerPixel) {
|
||||||
|
case 15:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE,
|
||||||
|
(*(Uint16 *) temp->pixels) & 0x00007FFF);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE,
|
||||||
|
(*(Uint32 *) temp->pixels) & 0x00FFFFFF);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create textures from the image */
|
||||||
|
texture = SDL_CreateTextureFromSurface(renderer, temp);
|
||||||
|
if (!texture) {
|
||||||
|
fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
|
||||||
|
SDL_FreeSurface(temp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
SDL_FreeSurface(temp);
|
||||||
|
|
||||||
|
/* We're ready to roll. :) */
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Draw(DrawState *s)
|
||||||
|
{
|
||||||
|
SDL_Rect viewport;
|
||||||
|
SDL_Texture *target;
|
||||||
|
|
||||||
|
SDL_RenderGetViewport(s->renderer, &viewport);
|
||||||
|
|
||||||
|
target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h);
|
||||||
|
SDL_SetTargetTexture(s->renderer, target);
|
||||||
|
|
||||||
|
/* Draw the background */
|
||||||
|
SDL_RenderCopy(s->renderer, s->background, NULL, NULL);
|
||||||
|
|
||||||
|
/* Scale and draw the sprite */
|
||||||
|
s->sprite_rect.w += s->scale_direction;
|
||||||
|
s->sprite_rect.h += s->scale_direction;
|
||||||
|
if (s->scale_direction > 0) {
|
||||||
|
if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) {
|
||||||
|
s->scale_direction = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) {
|
||||||
|
s->scale_direction = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
|
||||||
|
s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
|
||||||
|
|
||||||
|
SDL_RenderCopy(s->renderer, s->sprite, NULL, &s->sprite_rect);
|
||||||
|
|
||||||
|
SDL_SetTargetTexture(s->renderer, NULL);
|
||||||
|
SDL_RenderCopy(s->renderer, target, NULL, NULL);
|
||||||
|
SDL_DestroyTexture(target);
|
||||||
|
|
||||||
|
/* Update the screen! */
|
||||||
|
SDL_RenderPresent(s->renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
DrawState *drawstates;
|
||||||
|
int i, done;
|
||||||
|
SDL_Event event;
|
||||||
|
int frames;
|
||||||
|
Uint32 then, now;
|
||||||
|
|
||||||
|
/* Initialize test framework */
|
||||||
|
state = CommonCreateState(argv, SDL_INIT_VIDEO);
|
||||||
|
if (!state) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i = 1; i < argc;) {
|
||||||
|
int consumed;
|
||||||
|
|
||||||
|
consumed = CommonArg(state, i);
|
||||||
|
if (consumed == 0) {
|
||||||
|
fprintf(stderr, "Usage: %s %s\n", argv[0], CommonUsage(state));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
i += consumed;
|
||||||
|
}
|
||||||
|
if (!CommonInit(state)) {
|
||||||
|
quit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawstates = SDL_stack_alloc(DrawState, state->num_windows);
|
||||||
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
|
DrawState *drawstate = &drawstates[i];
|
||||||
|
|
||||||
|
drawstate->window = state->windows[i];
|
||||||
|
drawstate->renderer = state->renderers[i];
|
||||||
|
drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp", SDL_TRUE);
|
||||||
|
drawstate->background = LoadTexture(drawstate->renderer, "sample.bmp", SDL_FALSE);
|
||||||
|
if (!drawstate->sprite || !drawstate->background) {
|
||||||
|
quit(2);
|
||||||
|
}
|
||||||
|
SDL_QueryTexture(drawstate->sprite, NULL, NULL,
|
||||||
|
&drawstate->sprite_rect.w, &drawstate->sprite_rect.h);
|
||||||
|
drawstate->scale_direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main render loop */
|
||||||
|
frames = 0;
|
||||||
|
then = SDL_GetTicks();
|
||||||
|
done = 0;
|
||||||
|
while (!done) {
|
||||||
|
/* Check for events */
|
||||||
|
++frames;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
CommonEvent(state, &event, &done);
|
||||||
|
}
|
||||||
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
|
Draw(&drawstates[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print out some timing information */
|
||||||
|
now = SDL_GetTicks();
|
||||||
|
if (now > then) {
|
||||||
|
double fps = ((double) frames * 1000) / (now - then);
|
||||||
|
printf("%2.2f frames per second\n", fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_stack_free(drawstates);
|
||||||
|
|
||||||
|
quit(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
Loading…
Add table
Add a link
Reference in a new issue