Added SDL 1c0f6952e65e.

This commit is contained in:
rude
2015-03-15 15:47:43 +01:00
parent 4d04ac181e
commit 6a2aff6450
1109 changed files with 160136 additions and 33995 deletions
+5
View File
@@ -19,6 +19,8 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_internal.h"
#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED
#include "SDL_stdinc.h"
#include "SDL_d3dmath.h"
@@ -126,6 +128,9 @@ Float4X4 MatrixRotationZ(float r)
m._33 = 1.0f;
m._44 = 1.0f;
return m;
}
#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */
+3
View File
@@ -20,6 +20,7 @@
*/
#include "../SDL_internal.h"
#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED
/* Direct3D matrix math functions */
@@ -66,4 +67,6 @@ Float4X4 MatrixRotationX(float r);
Float4X4 MatrixRotationY(float r);
Float4X4 MatrixRotationZ(float r);
#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */
+41 -12
View File
@@ -115,6 +115,12 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
}
if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
/* Make sure we're operating on the default render target */
SDL_Texture *saved_target = SDL_GetRenderTarget(renderer);
if (saved_target) {
SDL_SetRenderTarget(renderer, NULL);
}
if (renderer->logical_w) {
UpdateLogicalSize(renderer);
} else {
@@ -140,6 +146,10 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
renderer->UpdateViewport(renderer);
}
}
if (saved_target) {
SDL_SetRenderTarget(renderer, saved_target);
}
} else if (event->window.event == SDL_WINDOWEVENT_HIDDEN) {
renderer->hidden = SDL_TRUE;
} else if (event->window.event == SDL_WINDOWEVENT_SHOWN) {
@@ -350,7 +360,7 @@ SDL_GetRendererOutputSize(SDL_Renderer * renderer, int *w, int *h)
SDL_GetWindowSize(renderer->window, w, h);
return 0;
} else {
/* This should never happen */
SDL_assert(0 && "This should never happen");
return SDL_SetError("Renderer doesn't support querying output size");
}
}
@@ -404,6 +414,10 @@ SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int
if (!format) {
format = renderer->info.texture_formats[0];
}
if (SDL_BYTESPERPIXEL(format) == 0) {
SDL_SetError("Invalid texture format");
return NULL;
}
if (SDL_ISPIXELFORMAT_INDEXED(format)) {
SDL_SetError("Palettized textures are not supported");
return NULL;
@@ -536,6 +550,10 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
/* Set up a destination surface for the texture update */
dst_fmt = SDL_AllocFormat(format);
if (!dst_fmt) {
SDL_DestroyTexture(texture);
return NULL;
}
temp = SDL_ConvertSurface(surface, dst_fmt, 0);
SDL_FreeFormat(dst_fmt);
if (temp) {
@@ -908,12 +926,12 @@ int SDL_UpdateYUVTexture(SDL_Texture * texture, const SDL_Rect * rect,
SDL_assert(!texture->native);
renderer = texture->renderer;
SDL_assert(renderer->UpdateTextureYUV);
if (renderer->UpdateTextureYUV) {
return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
} else {
return SDL_Unsupported();
}
}
if (renderer->UpdateTextureYUV) {
return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
} else {
return SDL_Unsupported();
}
}
}
static int
@@ -970,8 +988,8 @@ static void
SDL_UnlockTextureYUV(SDL_Texture * texture)
{
SDL_Texture *native = texture->native;
void *native_pixels;
int native_pitch;
void *native_pixels = NULL;
int native_pitch = 0;
SDL_Rect rect;
rect.x = 0;
@@ -991,8 +1009,8 @@ static void
SDL_UnlockTextureNative(SDL_Texture * texture)
{
SDL_Texture *native = texture->native;
void *native_pixels;
int native_pitch;
void *native_pixels = NULL;
int native_pitch = 0;
const SDL_Rect *rect = &texture->locked_rect;
const void* pixels = (void *) ((Uint8 *) texture->pixels +
rect->y * texture->pitch +
@@ -1067,6 +1085,7 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
/* Make a backup of the viewport */
renderer->viewport_backup = renderer->viewport;
renderer->clip_rect_backup = renderer->clip_rect;
renderer->clipping_enabled_backup = renderer->clipping_enabled;
renderer->scale_backup = renderer->scale;
renderer->logical_w_backup = renderer->logical_w;
renderer->logical_h_backup = renderer->logical_h;
@@ -1089,6 +1108,7 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
} else {
renderer->viewport = renderer->viewport_backup;
renderer->clip_rect = renderer->clip_rect_backup;
renderer->clipping_enabled = renderer->clipping_enabled_backup;
renderer->scale = renderer->scale_backup;
renderer->logical_w = renderer->logical_w_backup;
renderer->logical_h = renderer->logical_h_backup;
@@ -1113,7 +1133,7 @@ SDL_GetRenderTarget(SDL_Renderer *renderer)
static int
UpdateLogicalSize(SDL_Renderer *renderer)
{
int w, h;
int w = 1, h = 1;
float want_aspect;
float real_aspect;
float scale;
@@ -1229,11 +1249,13 @@ SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
CHECK_RENDERER_MAGIC(renderer, -1)
if (rect) {
renderer->clipping_enabled = SDL_TRUE;
renderer->clip_rect.x = (int)SDL_floor(rect->x * renderer->scale.x);
renderer->clip_rect.y = (int)SDL_floor(rect->y * renderer->scale.y);
renderer->clip_rect.w = (int)SDL_ceil(rect->w * renderer->scale.x);
renderer->clip_rect.h = (int)SDL_ceil(rect->h * renderer->scale.y);
} else {
renderer->clipping_enabled = SDL_FALSE;
SDL_zero(renderer->clip_rect);
}
return renderer->UpdateClipRect(renderer);
@@ -1252,6 +1274,13 @@ SDL_RenderGetClipRect(SDL_Renderer * renderer, SDL_Rect * rect)
}
}
SDL_bool
SDL_RenderIsClipEnabled(SDL_Renderer * renderer)
{
CHECK_RENDERER_MAGIC(renderer, SDL_FALSE)
return renderer->clipping_enabled;
}
int
SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY)
{
+4
View File
@@ -143,6 +143,10 @@ struct SDL_Renderer
SDL_Rect clip_rect;
SDL_Rect clip_rect_backup;
/* Wether or not the clipping rectangle is used. */
SDL_bool clipping_enabled;
SDL_bool clipping_enabled_backup;
/* The render output coordinate scale */
SDL_FPoint scale;
SDL_FPoint scale_backup;
+6 -1
View File
@@ -1274,11 +1274,16 @@ SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
Uint32 target_format, int w, int h, void *pixels,
int pitch)
{
const int targetbpp = SDL_BYTESPERPIXEL(target_format);
int stretch;
int scale_2x;
Uint8 *lum, *Cr, *Cb;
int mod;
if (targetbpp == 0) {
return SDL_SetError("Invalid target pixel format");
}
/* Make sure we're set up to display in the desired format */
if (target_format != swdata->target_format) {
if (SDL_SW_SetupYUVDisplay(swdata, target_format) < 0) {
@@ -1366,7 +1371,7 @@ SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
default:
return SDL_SetError("Unsupported YUV format in copy");
}
mod = (pitch / SDL_BYTESPERPIXEL(target_format));
mod = (pitch / targetbpp);
if (scale_2x) {
mod -= (swdata->w * 2);
+280 -189
View File
@@ -41,6 +41,8 @@
#ifdef ASSEMBLE_SHADER
#pragma comment(lib, "d3dx9.lib")
/**************************************************************************
* ID3DXBuffer:
* ------------
@@ -124,6 +126,7 @@ static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
static void D3D_WindowEvent(SDL_Renderer * renderer,
const SDL_WindowEvent *event);
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
@@ -189,13 +192,23 @@ typedef struct
typedef struct
{
SDL_bool dirty;
int w, h;
DWORD usage;
Uint32 format;
IDirect3DTexture9 *texture;
IDirect3DTexture9 *staging;
} D3D_TextureRep;
typedef struct
{
D3D_TextureRep texture;
D3DTEXTUREFILTERTYPE scaleMode;
/* YV12 texture support */
SDL_bool yuv;
IDirect3DTexture9 *utexture;
IDirect3DTexture9 *vtexture;
D3D_TextureRep utexture;
D3D_TextureRep vtexture;
Uint8 *pixels;
int pitch;
SDL_Rect locked_rect;
@@ -408,6 +421,8 @@ D3D_Reset(SDL_Renderer * renderer)
for (texture = renderer->textures; texture; texture = texture->next) {
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
D3D_DestroyTexture(renderer, texture);
} else {
D3D_RecreateTexture(renderer, texture);
}
}
@@ -452,15 +467,21 @@ D3D_ActivateRenderer(SDL_Renderer * renderer)
if (data->updateSize) {
SDL_Window *window = renderer->window;
int w, h;
Uint32 window_flags = SDL_GetWindowFlags(window);
SDL_GetWindowSize(window, &w, &h);
data->pparams.BackBufferWidth = w;
data->pparams.BackBufferHeight = h;
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
data->pparams.BackBufferFormat =
PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));
if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
SDL_DisplayMode fullscreen_mode;
SDL_GetWindowDisplayMode(window, &fullscreen_mode);
data->pparams.Windowed = FALSE;
data->pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
data->pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
} else {
data->pparams.Windowed = TRUE;
data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
data->pparams.FullScreen_RefreshRateInHz = 0;
}
if (D3D_Reset(renderer) < 0) {
return -1;
@@ -555,25 +576,16 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
pparams.hDeviceWindow = windowinfo.info.win.window;
pparams.BackBufferWidth = w;
pparams.BackBufferHeight = h;
if (window_flags & SDL_WINDOW_FULLSCREEN) {
pparams.BackBufferFormat =
PixelFormatToD3DFMT(fullscreen_mode.format);
} else {
pparams.BackBufferFormat = D3DFMT_UNKNOWN;
}
pparams.BackBufferCount = 1;
pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
if (window_flags & SDL_WINDOW_FULLSCREEN) {
if ((window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
pparams.Windowed = TRUE;
pparams.FullScreen_RefreshRateInHz = 0;
} else {
pparams.Windowed = FALSE;
pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
}
if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
pparams.Windowed = FALSE;
pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
} else {
pparams.Windowed = TRUE;
pparams.BackBufferFormat = D3DFMT_UNKNOWN;
pparams.FullScreen_RefreshRateInHz = 0;
}
if (flags & SDL_RENDERER_PRESENTVSYNC) {
@@ -643,7 +655,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
}
/* Store the default render target */
IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget );
IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
data->currentRenderTarget = NULL;
/* Set up parameters for rendering */
@@ -682,7 +694,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
PS_OUTPUT YUV420( VS_OUTPUT In )
{
const float3 offset = {-0.0625, -0.5, -0.5};
const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
const float3 Rcoeff = {1.164, 0.000, 1.596};
const float3 Gcoeff = {1.164, -0.391, -0.813};
const float3 Bcoeff = {1.164, 2.018, 0.000};
@@ -714,7 +726,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
*/
const char *shader_text =
"ps_2_0\n"
"def c0, -0.0625, -0.5, -0.5, 1\n"
"def c0, -0.0627451017, -0.501960814, -0.501960814, 1\n"
"def c1, 1.16400003, 0, 1.59599996, 0\n"
"def c2, 1.16400003, -0.391000003, -0.813000023, 0\n"
"def c3, 1.16400003, 2.01799989, 0, 0\n"
@@ -751,7 +763,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
}
#else
const DWORD shader_data[] = {
0xffff0200, 0x05000051, 0xa00f0000, 0xbd800000, 0xbf000000, 0xbf000000,
0xffff0200, 0x05000051, 0xa00f0000, 0xbd808081, 0xbf008081, 0xbf008081,
0x3f800000, 0x05000051, 0xa00f0001, 0x3f94fdf4, 0x00000000, 0x3fcc49ba,
0x00000000, 0x05000051, 0xa00f0002, 0x3f94fdf4, 0xbec83127, 0xbf5020c5,
0x00000000, 0x05000051, 0xa00f0003, 0x3f94fdf4, 0x400126e9, 0x00000000,
@@ -805,74 +817,85 @@ GetScaleQuality(void)
}
static int
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, int w, int h)
{
D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *data;
D3DPOOL pool;
DWORD usage;
HRESULT result;
data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
if (!data) {
return SDL_OutOfMemory();
}
data->scaleMode = GetScaleQuality();
texture->dirty = SDL_FALSE;
texture->w = w;
texture->h = h;
texture->usage = usage;
texture->format = format;
texture->driverdata = data;
#ifdef USE_DYNAMIC_TEXTURE
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_DYNAMIC;
} else
#endif
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
/* D3DPOOL_MANAGED does not work with D3DUSAGE_RENDERTARGET */
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_RENDERTARGET;
} else {
pool = D3DPOOL_MANAGED;
usage = 0;
}
result =
IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
texture->h, 1, usage,
PixelFormatToD3DFMT(texture->format),
pool, &data->texture, NULL);
result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
PixelFormatToD3DFMT(format),
D3DPOOL_DEFAULT, &texture->texture, NULL);
if (FAILED(result)) {
return D3D_SetError("CreateTexture()", result);
return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
}
return 0;
}
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
data->yuv = SDL_TRUE;
result =
IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
texture->h / 2, 1, usage,
PixelFormatToD3DFMT(texture->format),
pool, &data->utexture, NULL);
static int
D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture)
{
HRESULT result;
if (texture->staging == NULL) {
result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
PixelFormatToD3DFMT(texture->format),
D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
if (FAILED(result)) {
return D3D_SetError("CreateTexture()", result);
}
result =
IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
texture->h / 2, 1, usage,
PixelFormatToD3DFMT(texture->format),
pool, &data->vtexture, NULL);
if (FAILED(result)) {
return D3D_SetError("CreateTexture()", result);
return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result);
}
}
return 0;
}
static int
D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool full_texture, int x, int y, int w, int h, const void *pixels, int pitch)
D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
{
HRESULT result;
if (texture->dirty && texture->staging) {
if (!texture->texture) {
result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL);
if (FAILED(result)) {
return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
}
}
result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
if (FAILED(result)) {
return D3D_SetError("UpdateTexture()", result);
}
texture->dirty = SDL_FALSE;
}
result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
}
return 0;
}
static int
D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int w, int h)
{
if (texture->texture) {
IDirect3DTexture9_Release(texture->texture);
texture->texture = NULL;
}
if (texture->staging) {
IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
texture->dirty = SDL_TRUE;
}
return 0;
}
static int
D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int x, int y, int w, int h, const void *pixels, int pitch)
{
RECT d3drect;
D3DLOCKED_RECT locked;
@@ -881,16 +904,16 @@ D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool fu
int row, length;
HRESULT result;
if (full_texture) {
result = IDirect3DTexture9_LockRect(texture, 0, &locked, NULL, D3DLOCK_DISCARD);
} else {
d3drect.left = x;
d3drect.right = x + w;
d3drect.top = y;
d3drect.bottom = y + h;
result = IDirect3DTexture9_LockRect(texture, 0, &locked, &d3drect, 0);
if (D3D_CreateStagingTexture(device, texture) < 0) {
return -1;
}
d3drect.left = x;
d3drect.right = x + w;
d3drect.top = y;
d3drect.bottom = y + h;
result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0);
if (FAILED(result)) {
return D3D_SetError("LockRect()", result);
}
@@ -913,46 +936,117 @@ D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool fu
dst += locked.Pitch;
}
}
IDirect3DTexture9_UnlockRect(texture, 0);
result = IDirect3DTexture9_UnlockRect(texture->staging, 0);
if (FAILED(result)) {
return D3D_SetError("UnlockRect()", result);
}
texture->dirty = SDL_TRUE;
return 0;
}
static void
D3D_DestroyTextureRep(D3D_TextureRep *texture)
{
if (texture->texture) {
IDirect3DTexture9_Release(texture->texture);
texture->texture = NULL;
}
if (texture->staging) {
IDirect3DTexture9_Release(texture->staging);
texture->staging = NULL;
}
}
static int
D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *texturedata;
DWORD usage;
texturedata = (D3D_TextureData *) SDL_calloc(1, sizeof(*texturedata));
if (!texturedata) {
return SDL_OutOfMemory();
}
texturedata->scaleMode = GetScaleQuality();
texture->driverdata = texturedata;
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
usage = D3DUSAGE_RENDERTARGET;
} else {
usage = 0;
}
if (D3D_CreateTextureRep(data->device, &texturedata->texture, usage, texture->format, texture->w, texture->h) < 0) {
return -1;
}
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
texturedata->yuv = SDL_TRUE;
if (D3D_CreateTextureRep(data->device, &texturedata->utexture, usage, texture->format, texture->w / 2, texture->h / 2) < 0) {
return -1;
}
if (D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, texture->w / 2, texture->h / 2) < 0) {
return -1;
}
}
return 0;
}
static int
D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
if (D3D_RecreateTextureRep(data->device, &texturedata->texture, texture->format, texture->w, texture->h) < 0) {
return -1;
}
if (texturedata->yuv) {
if (D3D_RecreateTextureRep(data->device, &texturedata->utexture, texture->format, texture->w / 2, texture->h / 2) < 0) {
return -1;
}
if (D3D_RecreateTextureRep(data->device, &texturedata->vtexture, texture->format, texture->w / 2, texture->h / 2) < 0) {
return -1;
}
}
return 0;
}
static int
D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
{
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
SDL_bool full_texture = SDL_FALSE;
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
#ifdef USE_DYNAMIC_TEXTURE
if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
rect->x == 0 && rect->y == 0 &&
rect->w == texture->w && rect->h == texture->h) {
full_texture = SDL_TRUE;
}
#endif
if (!data) {
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
}
if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
if (D3D_UpdateTextureRep(data->device, &texturedata->texture, texture->format, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
return -1;
}
if (data->yuv) {
if (texturedata->yuv) {
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->vtexture : data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
return -1;
}
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->utexture : data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
return -1;
}
}
@@ -966,29 +1060,21 @@ D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch)
{
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
SDL_bool full_texture = SDL_FALSE;
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
#ifdef USE_DYNAMIC_TEXTURE
if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
rect->x == 0 && rect->y == 0 &&
rect->w == texture->w && rect->h == texture->h) {
full_texture = SDL_TRUE;
}
#endif
if (!data) {
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
}
if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
if (D3D_UpdateTextureRep(data->device, &texturedata->texture, texture->format, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
return -1;
}
if (D3D_UpdateTextureInternal(data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch) < 0) {
if (D3D_UpdateTextureRep(data->device, &texturedata->utexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch) < 0) {
return -1;
}
if (D3D_UpdateTextureInternal(data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch) < 0) {
if (D3D_UpdateTextureRep(data->device, &texturedata->vtexture, texture->format, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch) < 0) {
return -1;
}
return 0;
@@ -998,37 +1084,45 @@ static int
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, void **pixels, int *pitch)
{
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
RECT d3drect;
D3DLOCKED_RECT locked;
HRESULT result;
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
IDirect3DDevice9 *device = data->device;
if (!data) {
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
}
if (data->yuv) {
texturedata->locked_rect = *rect;
if (texturedata->yuv) {
/* It's more efficient to upload directly... */
if (!data->pixels) {
data->pitch = texture->w;
data->pixels = (Uint8 *)SDL_malloc((texture->h * data->pitch * 3) / 2);
if (!data->pixels) {
if (!texturedata->pixels) {
texturedata->pitch = texture->w;
texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2);
if (!texturedata->pixels) {
return SDL_OutOfMemory();
}
}
data->locked_rect = *rect;
*pixels =
(void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
(void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
*pitch = data->pitch;
*pitch = texturedata->pitch;
} else {
RECT d3drect;
D3DLOCKED_RECT locked;
HRESULT result;
if (D3D_CreateStagingTexture(device, &texturedata->texture) < 0) {
return -1;
}
d3drect.left = rect->x;
d3drect.right = rect->x + rect->w;
d3drect.top = rect->y;
d3drect.bottom = rect->y + rect->h;
result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
result = IDirect3DTexture9_LockRect(texturedata->texture.staging, 0, &locked, &d3drect, 0);
if (FAILED(result)) {
return D3D_SetError("LockRect()", result);
}
@@ -1041,21 +1135,23 @@ D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
static void
D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
/*D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;*/
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
if (!data) {
if (!texturedata) {
return;
}
if (data->yuv) {
const SDL_Rect *rect = &data->locked_rect;
if (texturedata->yuv) {
const SDL_Rect *rect = &texturedata->locked_rect;
void *pixels =
(void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
(void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
D3D_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
} else {
IDirect3DTexture9_UnlockRect(data->texture, 0);
}
IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
texturedata->texture.dirty = SDL_TRUE;
}
}
static int
@@ -1063,7 +1159,9 @@ D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
{
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
D3D_TextureData *texturedata;
D3D_TextureRep *texturerep;
HRESULT result;
IDirect3DDevice9 *device = data->device;
/* Release the previous render target if it wasn't the default one */
if (data->currentRenderTarget != NULL) {
@@ -1082,7 +1180,25 @@ D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
return -1;
}
result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture, 0, &data->currentRenderTarget);
/* Make sure the render target is updated if it was locked and written to */
texturerep = &texturedata->texture;
if (texturerep->dirty && texturerep->staging) {
if (!texturerep->texture) {
result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h, 1, texturerep->usage,
PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL);
if (FAILED(result)) {
return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
}
}
result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texturerep->staging, (IDirect3DBaseTexture9 *)texturerep->texture);
if (FAILED(result)) {
return D3D_SetError("UpdateTexture()", result);
}
texturerep->dirty = SDL_FALSE;
}
result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget);
if(FAILED(result)) {
return D3D_SetError("GetSurfaceLevel()", result);
}
@@ -1145,12 +1261,13 @@ D3D_UpdateViewport(SDL_Renderer * renderer)
static int
D3D_UpdateClipRect(SDL_Renderer * renderer)
{
const SDL_Rect *rect = &renderer->clip_rect;
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
RECT r;
HRESULT result;
if (!SDL_RectEmpty(rect)) {
if (renderer->clipping_enabled) {
const SDL_Rect *rect = &renderer->clip_rect;
RECT r;
HRESULT result;
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
r.left = rect->x;
r.top = rect->y;
@@ -1527,11 +1644,8 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_UpdateTextureScaleMode(data, texturedata, 0);
result =
IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
texturedata->texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
return -1;
}
if (texturedata->yuv) {
@@ -1540,18 +1654,11 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_UpdateTextureScaleMode(data, texturedata, 1);
D3D_UpdateTextureScaleMode(data, texturedata, 2);
result =
IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
texturedata->utexture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
return -1;
}
result =
IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
texturedata->vtexture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
return -1;
}
}
@@ -1665,16 +1772,13 @@ D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
modelMatrix = MatrixMultiply(
MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
MatrixTranslation(dstrect->x + center->x, dstrect->y + center->y, 0)
);
);
IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
D3D_UpdateTextureScaleMode(data, texturedata, 0);
result =
IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
texturedata->texture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
return -1;
}
if (texturedata->yuv) {
@@ -1682,19 +1786,12 @@ D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_UpdateTextureScaleMode(data, texturedata, 1);
D3D_UpdateTextureScaleMode(data, texturedata, 2);
result =
IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
texturedata->utexture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
return -1;
}
result =
IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
texturedata->vtexture);
if (FAILED(result)) {
return D3D_SetError("SetTexture()", result);
if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
return -1;
}
}
@@ -1734,9 +1831,10 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
D3DLOCKED_RECT locked;
HRESULT result;
result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
if (FAILED(result)) {
return D3D_SetError("GetBackBuffer()", result);
if (data->currentRenderTarget) {
backBuffer = data->currentRenderTarget;
} else {
backBuffer = data->defaultRenderTarget;
}
result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
@@ -1777,7 +1875,6 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
IDirect3DSurface9_UnlockRect(surface);
IDirect3DSurface9_Release(surface);
IDirect3DSurface9_Release(backBuffer);
return 0;
}
@@ -1815,15 +1912,9 @@ D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (!data) {
return;
}
if (data->texture) {
IDirect3DTexture9_Release(data->texture);
}
if (data->utexture) {
IDirect3DTexture9_Release(data->utexture);
}
if (data->vtexture) {
IDirect3DTexture9_Release(data->vtexture);
}
D3D_DestroyTextureRep(&data->texture);
D3D_DestroyTextureRep(&data->utexture);
D3D_DestroyTextureRep(&data->vtexture);
SDL_free(data->pixels);
SDL_free(data);
texture->driverdata = NULL;
@@ -1870,7 +1961,7 @@ SDL_RenderGetD3D9Device(SDL_Renderer * renderer)
#if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
// Make sure that this is a D3D renderer
/* Make sure that this is a D3D renderer */
if (renderer->DestroyRenderer != D3D_DestroyRenderer) {
SDL_SetError("Renderer is not a D3D renderer");
return NULL;
@@ -29,12 +29,17 @@
#include "SDL_syswm.h"
#include "../SDL_sysrender.h"
#include "../SDL_d3dmath.h"
/* #include "SDL_log.h" */
#include <d3d11_1.h>
#ifdef __WINRT__
#if NTDDI_VERSION > NTDDI_WIN8
#include <DXGI1_3.h>
#endif
#include "SDL_render_winrt.h"
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
@@ -134,6 +139,7 @@ typedef struct
/* Defined here so we don't have to include uuid.lib */
static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
static const GUID IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
static const GUID IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
static const GUID IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
static const GUID IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
static const GUID IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } };
@@ -357,7 +363,7 @@ static const DWORD D3D11_PixelShader_Textures[] = {
float4 main(PixelShaderInput input) : SV_TARGET
{
const float3 offset = {-0.0625, -0.5, -0.5};
const float3 offset = {-0.0627451017, -0.501960814, -0.501960814};
const float3 Rcoeff = {1.164, 0.000, 1.596};
const float3 Gcoeff = {1.164, -0.391, -0.813};
const float3 Bcoeff = {1.164, 2.018, 0.000};
@@ -381,12 +387,12 @@ static const DWORD D3D11_PixelShader_Textures[] = {
*/
#if defined(D3D11_USE_SHADER_MODEL_4_0_level_9_1)
static const DWORD D3D11_PixelShader_YUV[] = {
0x43425844, 0x04e69cba, 0x74ce6dd2, 0x7fcf84cb, 0x3003d677, 0x00000001,
0x43425844, 0x2321c6c6, 0xf14df2d1, 0xc79d068d, 0x8e672abf, 0x00000001,
0x000005e8, 0x00000006, 0x00000038, 0x000001dc, 0x000003bc, 0x00000438,
0x00000540, 0x000005b4, 0x396e6f41, 0x0000019c, 0x0000019c, 0xffff0200,
0x0000016c, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003,
0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0200, 0x05000051,
0xa00f0000, 0xbd800000, 0xbf000000, 0xbf000000, 0x3f800000, 0x05000051,
0xa00f0000, 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051,
0xa00f0001, 0x3f94fdf4, 0x3fcc49ba, 0x00000000, 0x00000000, 0x05000051,
0xa00f0002, 0x3f94fdf4, 0xbec83127, 0xbf5020c5, 0x00000000, 0x05000051,
0xa00f0003, 0x3f94fdf4, 0x400126e9, 0x00000000, 0x00000000, 0x0200001f,
@@ -413,7 +419,7 @@ static const DWORD D3D11_PixelShader_YUV[] = {
0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000002, 0x00106000,
0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x0010000a, 0x00000001,
0x0a000000, 0x00100072, 0x00000000, 0x00100246, 0x00000000, 0x00004002,
0xbd800000, 0xbf000000, 0xbf000000, 0x00000000, 0x0a00000f, 0x00100012,
0xbd808081, 0xbf008081, 0xbf008081, 0x00000000, 0x0a00000f, 0x00100012,
0x00000001, 0x00100086, 0x00000000, 0x00004002, 0x3f94fdf4, 0x3fcc49ba,
0x00000000, 0x00000000, 0x0a000010, 0x00100022, 0x00000001, 0x00100246,
0x00000000, 0x00004002, 0x3f94fdf4, 0xbec83127, 0xbf5020c5, 0x00000000,
@@ -447,12 +453,12 @@ static const DWORD D3D11_PixelShader_YUV[] = {
};
#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3)
static const DWORD D3D11_PixelShader_YUV[] = {
0x43425844, 0xe6d969fc, 0x63cac33c, 0xa4926502, 0x5d788135, 0x00000001,
0x43425844, 0x6ede7360, 0x45ff5f8a, 0x34ac92ba, 0xb865f5e0, 0x00000001,
0x000005c0, 0x00000006, 0x00000038, 0x000001b4, 0x00000394, 0x00000410,
0x00000518, 0x0000058c, 0x396e6f41, 0x00000174, 0x00000174, 0xffff0200,
0x00000144, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003,
0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0201, 0x05000051,
0xa00f0000, 0xbd800000, 0xbf000000, 0x3f800000, 0x00000000, 0x05000051,
0xa00f0000, 0xbd808081, 0xbf008081, 0x3f800000, 0x00000000, 0x05000051,
0xa00f0001, 0x3f94fdf4, 0x3fcc49ba, 0x00000000, 0x400126e9, 0x05000051,
0xa00f0002, 0x3f94fdf4, 0xbec83127, 0xbf5020c5, 0x00000000, 0x0200001f,
0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f,
@@ -477,7 +483,7 @@ static const DWORD D3D11_PixelShader_YUV[] = {
0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, 0x00107e46,
0x00000002, 0x00106000, 0x00000000, 0x05000036, 0x00100042, 0x00000000,
0x0010000a, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, 0x00100246,
0x00000000, 0x00004002, 0xbd800000, 0xbf000000, 0xbf000000, 0x00000000,
0x00000000, 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, 0x00000000,
0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, 0x00004002,
0x3f94fdf4, 0x3fcc49ba, 0x00000000, 0x00000000, 0x0a000010, 0x00100022,
0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f94fdf4, 0xbec83127,
@@ -823,9 +829,24 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->driverdata = data;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
/* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
* Failure to use it seems to either result in:
*
* - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned
* off (framerate doesn't get capped), but nothing appears on-screen
*
* - with the D3D11 debug runtime turned ON, vsync gets automatically
* turned back on, and the following gets output to the debug console:
*
* DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ]
*/
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
#else
if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
#endif
/* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
* order to give init functions access to the underlying window handle:
@@ -846,10 +867,17 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
}
static void
D3D11_DestroyRenderer(SDL_Renderer * renderer)
D3D11_ReleaseAll(SDL_Renderer * renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
SDL_Texture *texture = NULL;
/* Release all textures */
for (texture = renderer->textures; texture; texture = texture->next) {
D3D11_DestroyTexture(renderer, texture);
}
/* Release/reset everything else */
if (data) {
SAFE_RELEASE(data->dxgiFactory);
SAFE_RELEASE(data->dxgiAdapter);
@@ -873,12 +901,35 @@ D3D11_DestroyRenderer(SDL_Renderer * renderer)
SAFE_RELEASE(data->clippedRasterizer);
SAFE_RELEASE(data->vertexShaderConstants);
data->swapEffect = (DXGI_SWAP_EFFECT) 0;
data->rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
data->currentRenderTargetView = NULL;
data->currentRasterizerState = NULL;
data->currentBlendState = NULL;
data->currentShader = NULL;
data->currentShaderResource = NULL;
data->currentSampler = NULL;
/* Unload the D3D libraries. This should be done last, in order
* to prevent IUnknown::Release() calls from crashing.
*/
if (data->hD3D11Mod) {
SDL_UnloadObject(data->hD3D11Mod);
data->hD3D11Mod = NULL;
}
if (data->hDXGIMod) {
SDL_UnloadObject(data->hDXGIMod);
data->hDXGIMod = NULL;
}
}
}
static void
D3D11_DestroyRenderer(SDL_Renderer * renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
D3D11_ReleaseAll(renderer);
if (data) {
SDL_free(data);
}
SDL_free(renderer);
@@ -1293,11 +1344,23 @@ D3D11_IsDisplayRotated90Degrees(DXGI_MODE_ROTATION rotation)
}
}
static int
D3D11_GetRotationForCurrentRenderTarget(SDL_Renderer * renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
if (data->currentOffscreenRenderTargetView) {
return DXGI_MODE_ROTATION_IDENTITY;
} else {
return data->rotation;
}
}
static int
D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRect, D3D11_RECT * outRect)
{
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
switch (data->rotation) {
const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
switch (rotation) {
case DXGI_MODE_ROTATION_IDENTITY:
outRect->left = sdlRect->x;
outRect->right = sdlRect->x + sdlRect->w;
@@ -1355,6 +1418,7 @@ D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
swapChainDesc.Scaling = DXGI_SCALING_STRETCH; /* On phone, only stretch and aspect-ratio stretch scaling are allowed. */
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; /* On phone, no swap effects are supported. */
/* TODO, WinRT: see if Win 8.x DXGI_SWAP_CHAIN_DESC1 settings are available on Windows Phone 8.1, and if there's any advantage to having them on */
#else
if (usingXAML) {
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
@@ -1417,6 +1481,8 @@ D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForHwnd", result);
goto done;
}
IDXGIFactory_MakeWindowAssociation(data->dxgiFactory, windowinfo.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES);
#else
SDL_SetError(__FUNCTION__", Unable to find something to attach a swap chain to");
goto done;
@@ -1447,6 +1513,7 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
*/
SDL_GetWindowSize(renderer->window, &w, &h);
data->rotation = D3D11_GetCurrentRotation();
/* SDL_Log("%s: windowSize={%d,%d}, orientation=%d\n", __FUNCTION__, w, h, (int)data->rotation); */
if (D3D11_IsDisplayRotated90Degrees(data->rotation)) {
int tmp = w;
w = h;
@@ -1463,7 +1530,15 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
DXGI_FORMAT_UNKNOWN,
0
);
if (FAILED(result)) {
if (result == DXGI_ERROR_DEVICE_REMOVED) {
/* If the device was removed for any reason, a new device and swap chain will need to be created. */
D3D11_HandleDeviceLost(renderer);
/* Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
* and correctly set up the new device.
*/
goto done;
} else if (FAILED(result)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain::ResizeBuffers", result);
goto done;
}
@@ -1476,11 +1551,21 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
}
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
/* Set the proper rotation for the swap chain, and generate the
* 3D matrix transformation for rendering to the rotated swap chain.
/* Set the proper rotation for the swap chain.
*
* To note, the call for this, IDXGISwapChain1::SetRotation, is not necessary
* on Windows Phone, nor is it supported there. It's only needed in Windows 8/RT.
* on Windows Phone 8.0, nor is it supported there.
*
* IDXGISwapChain1::SetRotation does seem to be available on Windows Phone 8.1,
* however I've yet to find a way to make it work. It might have something to
* do with IDXGISwapChain::ResizeBuffers appearing to not being available on
* Windows Phone 8.1 (it wasn't on Windows Phone 8.0), but I'm not 100% sure of this.
* The call doesn't appear to be entirely necessary though, and is a performance-related
* call, at least according to the following page on MSDN:
* http://code.msdn.microsoft.com/windowsapps/DXGI-swap-chain-rotation-21d13d71
* -- David L.
*
* TODO, WinRT: reexamine the docs for IDXGISwapChain1::SetRotation, see if might be available, usable, and prudent-to-call on WinPhone 8.1
*/
if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
result = IDXGISwapChain1_SetRotation(data->swapChain, data->rotation);
@@ -1537,7 +1622,7 @@ D3D11_HandleDeviceLost(SDL_Renderer * renderer)
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
HRESULT result = S_OK;
/* FIXME: Need to release all resources - all textures are invalid! */
D3D11_ReleaseAll(renderer);
result = D3D11_CreateDeviceResources(renderer);
if (FAILED(result)) {
@@ -1551,9 +1636,37 @@ D3D11_HandleDeviceLost(SDL_Renderer * renderer)
return result;
}
/* Let the application know that the device has been reset */
{
SDL_Event event;
event.type = SDL_RENDER_DEVICE_RESET;
SDL_PushEvent(&event);
}
return S_OK;
}
void
D3D11_Trim(SDL_Renderer * renderer)
{
#ifdef __WINRT__
#if NTDDI_VERSION > NTDDI_WIN8
D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
HRESULT result = S_OK;
IDXGIDevice3 *dxgiDevice = NULL;
result = ID3D11Device_QueryInterface(data->d3dDevice, &IID_IDXGIDevice3, &dxgiDevice);
if (FAILED(result)) {
//WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to IDXGIDevice3", result);
return;
}
IDXGIDevice3_Trim(dxgiDevice);
SAFE_RELEASE(dxgiDevice);
#endif
#endif
}
static void
D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
@@ -2065,12 +2178,14 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
SDL_FRect orientationAlignedViewport;
BOOL swapDimensions;
D3D11_VIEWPORT viewport;
const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
if (renderer->viewport.w == 0 || renderer->viewport.h == 0) {
/* If the viewport is empty, assume that it is because
* SDL_CreateRenderer is calling it, and will call it again later
* with a non-empty viewport.
*/
/* SDL_Log("%s, no viewport was set!\n", __FUNCTION__); */
return 0;
}
@@ -2079,7 +2194,7 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
* default coordinate system) so rotations will be done in the opposite
* direction of the DXGI_MODE_ROTATION enumeration.
*/
switch (data->rotation) {
switch (rotation) {
case DXGI_MODE_ROTATION_IDENTITY:
projection = MatrixIdentity();
break;
@@ -2130,7 +2245,7 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
* a landscape mode, for all Windows 8/RT devices, or a portrait mode,
* for Windows Phone devices.
*/
swapDimensions = D3D11_IsDisplayRotated90Degrees(data->rotation);
swapDimensions = D3D11_IsDisplayRotated90Degrees(rotation);
if (swapDimensions) {
orientationAlignedViewport.x = (float) renderer->viewport.y;
orientationAlignedViewport.y = (float) renderer->viewport.x;
@@ -2150,6 +2265,7 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
viewport.Height = orientationAlignedViewport.h;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
/* SDL_Log("%s: D3D viewport = {%f,%f,%f,%f}\n", __FUNCTION__, viewport.TopLeftX, viewport.TopLeftY, viewport.Width, viewport.Height); */
ID3D11DeviceContext_RSSetViewports(data->d3dContext, 1, &viewport);
return 0;
@@ -2159,13 +2275,12 @@ static int
D3D11_UpdateClipRect(SDL_Renderer * renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
const SDL_Rect *rect = &renderer->clip_rect;
if (SDL_RectEmpty(rect)) {
if (!renderer->clipping_enabled) {
ID3D11DeviceContext_RSSetScissorRects(data->d3dContext, 0, NULL);
} else {
D3D11_RECT scissorRect;
if (D3D11_GetViewportAlignedD3DRect(renderer, rect, &scissorRect) != 0) {
if (D3D11_GetViewportAlignedD3DRect(renderer, &renderer->clip_rect, &scissorRect) != 0) {
/* D3D11_GetViewportAlignedD3DRect will have set the SDL error */
return -1;
}
@@ -2293,7 +2408,7 @@ D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
rendererData->currentRenderTargetView = renderTargetView;
}
if (SDL_RectEmpty(&renderer->clip_rect)) {
if (!renderer->clipping_enabled) {
rasterizerState = rendererData->mainRasterizer;
} else {
rasterizerState = rendererData->clippedRasterizer;
@@ -2827,6 +2942,8 @@ D3D11_RenderPresent(SDL_Renderer * renderer)
HRESULT result;
DXGI_PRESENT_PARAMETERS parameters;
SDL_zero(parameters);
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
syncInterval = 1;
presentFlags = 0;
@@ -2844,7 +2961,6 @@ D3D11_RenderPresent(SDL_Renderer * renderer)
* rects to improve efficiency in certain scenarios.
* This option is not available on Windows Phone 8, to note.
*/
SDL_zero(parameters);
result = IDXGISwapChain1_Present1(data->swapChain, syncInterval, presentFlags, &parameters);
#endif
@@ -23,6 +23,7 @@
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
#include "SDL_syswm.h"
#include "../../video/winrt/SDL_winrtvideo_cpp.h"
extern "C" {
#include "../SDL_sysrender.h"
}
@@ -79,11 +80,7 @@ D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer * renderer)
extern "C" DXGI_MODE_ROTATION
D3D11_GetCurrentRotation()
{
#if NTDDI_VERSION > NTDDI_WIN8
const DisplayOrientations currentOrientation = DisplayInformation::GetForCurrentView()->CurrentOrientation;
#else
const DisplayOrientations currentOrientation = DisplayProperties::CurrentOrientation;
#endif
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
switch (currentOrientation) {
+134 -63
View File
@@ -24,6 +24,7 @@
#include "SDL_hints.h"
#include "SDL_log.h"
#include "SDL_assert.h"
#include "SDL_opengl.h"
#include "../SDL_sysrender.h"
#include "SDL_shaders_gl.h"
@@ -120,6 +121,7 @@ typedef struct
GLDEBUGPROCARB next_error_callback;
GLvoid *next_error_userparam;
SDL_bool GL_ARB_texture_non_power_of_two_supported;
SDL_bool GL_ARB_texture_rectangle_supported;
struct {
GL_Shader shader;
@@ -163,8 +165,9 @@ typedef struct
int pitch;
SDL_Rect locked_rect;
/* YV12 texture support */
/* YUV texture support */
SDL_bool yuv;
SDL_bool nv12;
GLuint utexture;
GLuint vtexture;
@@ -289,7 +292,8 @@ GL_ActivateRenderer(SDL_Renderer * renderer)
{
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
if (SDL_CurrentContext != data->context) {
if (SDL_CurrentContext != data->context ||
SDL_GL_GetCurrentContext() != data->context) {
if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
return -1;
}
@@ -309,7 +313,7 @@ GL_ResetState(SDL_Renderer *renderer)
{
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
if (SDL_CurrentContext == data->context) {
if (SDL_GL_GetCurrentContext() == data->context) {
GL_UpdateViewport(renderer);
} else {
GL_ActivateRenderer(renderer);
@@ -331,16 +335,18 @@ GL_ResetState(SDL_Renderer *renderer)
}
static void APIENTRY
GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, void *userParam)
GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam)
{
SDL_Renderer *renderer = (SDL_Renderer *) userParam;
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
if (type == GL_DEBUG_TYPE_ERROR_ARB) {
/* Record this error */
++data->errors;
data->error_messages = SDL_realloc(data->error_messages, data->errors * sizeof(*data->error_messages));
if (data->error_messages) {
int errors = data->errors + 1;
char **error_messages = SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages));
if (error_messages) {
data->errors = errors;
data->error_messages = error_messages;
data->error_messages[data->errors-1] = SDL_strdup(message);
}
}
@@ -388,6 +394,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
GLint value;
Uint32 window_flags;
int profile_mask, major, minor;
SDL_bool changed_window = SDL_FALSE;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
@@ -396,32 +403,28 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
changed_window = SDL_TRUE;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
/* Uh oh, better try to put it back... */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
SDL_RecreateWindow(window, window_flags);
return NULL;
goto error;
}
}
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
goto error;
}
data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
if (!data) {
GL_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
goto error;
}
renderer->WindowEvent = GL_WindowEvent;
@@ -454,16 +457,16 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
data->context = SDL_GL_CreateContext(window);
if (!data->context) {
GL_DestroyRenderer(renderer);
return NULL;
goto error;
}
if (SDL_GL_MakeCurrent(window, data->context) < 0) {
GL_DestroyRenderer(renderer);
return NULL;
goto error;
}
if (GL_LoadFunctions(data) < 0) {
GL_DestroyRenderer(renderer);
return NULL;
goto error;
}
#ifdef __MACOSX__
@@ -499,9 +502,13 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
data->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}
if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
|| SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
if (SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
data->GL_ARB_texture_non_power_of_two_supported = SDL_TRUE;
} else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
}
if (data->GL_ARB_texture_rectangle_supported) {
data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value);
renderer->info.max_texture_width = value;
renderer->info.max_texture_height = value;
@@ -532,6 +539,8 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
if (data->shaders && data->num_texture_units >= 3) {
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_NV12;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
}
#ifdef __MACOSX__
@@ -558,6 +567,16 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
GL_ResetState(renderer);
return renderer;
error:
if (changed_window) {
/* Uh oh, better try to put it back... */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
SDL_RecreateWindow(window, window_flags);
}
return NULL;
}
static void
@@ -602,16 +621,18 @@ convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
break;
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_NV12:
case SDL_PIXELFORMAT_NV21:
*internalFormat = GL_LUMINANCE;
*format = GL_LUMINANCE;
*type = GL_UNSIGNED_BYTE;
break;
#ifdef __MACOSX__
case SDL_PIXELFORMAT_UYVY:
*internalFormat = GL_RGB8;
*format = GL_YCBCR_422_APPLE;
*type = GL_UNSIGNED_SHORT_8_8_APPLE;
break;
*internalFormat = GL_RGB8;
*format = GL_YCBCR_422_APPLE;
*type = GL_UNSIGNED_SHORT_8_8_APPLE;
break;
#endif
default:
return SDL_FALSE;
@@ -663,6 +684,11 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
/* Need to add size for the U and V planes */
size += (2 * (texture->h * data->pitch) / 4);
}
if (texture->format == SDL_PIXELFORMAT_NV12 ||
texture->format == SDL_PIXELFORMAT_NV21) {
/* Need to add size for the U/V plane */
size += ((texture->h * data->pitch) / 2);
}
data->pixels = SDL_calloc(1, size);
if (!data->pixels) {
SDL_free(data);
@@ -678,14 +704,22 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
GL_CheckError("", renderer);
renderdata->glGenTextures(1, &data->texture);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
if (GL_CheckError("glGenTextures()", renderer) < 0) {
if (data->pixels) {
SDL_free(data->pixels);
}
SDL_free(data);
return -1;
}
texture->driverdata = data;
if ((renderdata->GL_ARB_texture_rectangle_supported)
/* && texture->access != SDL_TEXTUREACCESS_TARGET */){
if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
data->type = GL_TEXTURE_2D;
texture_w = texture->w;
texture_h = texture->h;
data->texw = 1.0f;
data->texh = 1.0f;
} else if (renderdata->GL_ARB_texture_rectangle_supported) {
data->type = GL_TEXTURE_RECTANGLE_ARB;
texture_w = texture->w;
texture_h = texture->h;
@@ -789,6 +823,27 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
renderdata->glDisable(data->type);
}
if (texture->format == SDL_PIXELFORMAT_NV12 ||
texture->format == SDL_PIXELFORMAT_NV21) {
data->nv12 = SDL_TRUE;
renderdata->glGenTextures(1, &data->utexture);
renderdata->glEnable(data->type);
renderdata->glBindTexture(data->type, data->utexture);
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, GL_LUMINANCE_ALPHA, texture_w/2,
texture_h/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
renderdata->glDisable(data->type);
}
return GL_CheckError("", renderer);
}
@@ -798,14 +853,16 @@ GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
{
GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
GL_TextureData *data = (GL_TextureData *) texture->driverdata;
const int texturebpp = SDL_BYTESPERPIXEL(texture->format);
SDL_assert(texturebpp != 0); /* otherwise, division by zero later. */
GL_ActivateRenderer(renderer);
renderdata->glEnable(data->type);
renderdata->glBindTexture(data->type, data->texture);
renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
(pitch / SDL_BYTESPERPIXEL(texture->format)));
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / texturebpp));
renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
rect->h, data->format, data->formattype,
pixels);
@@ -834,6 +891,17 @@ GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
rect->w/2, rect->h/2,
data->format, data->formattype, pixels);
}
if (data->nv12) {
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2));
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
renderdata->glBindTexture(data->type, data->utexture);
renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
rect->w/2, rect->h/2,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
}
renderdata->glDisable(data->type);
return GL_CheckError("glTexSubImage2D()", renderer);
@@ -973,10 +1041,10 @@ GL_UpdateViewport(SDL_Renderer * renderer)
static int
GL_UpdateClipRect(SDL_Renderer * renderer)
{
const SDL_Rect *rect = &renderer->clip_rect;
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
if (!SDL_RectEmpty(rect)) {
if (renderer->clipping_enabled) {
const SDL_Rect *rect = &renderer->clip_rect;
data->glEnable(GL_SCISSOR_TEST);
data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
} else {
@@ -1170,15 +1238,10 @@ GL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
}
static int
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
GL_SetupCopy(SDL_Renderer * renderer, SDL_Texture * texture)
{
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GL_ActivateRenderer(renderer);
data->glEnable(texturedata->type);
if (texturedata->yuv) {
@@ -1190,6 +1253,12 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
if (texturedata->nv12) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
data->glBindTexture(texturedata->type, texturedata->utexture);
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
data->glBindTexture(texturedata->type, texturedata->texture);
if (texture->modMode) {
@@ -1201,10 +1270,33 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
GL_SetBlendMode(data, texture->blendMode);
if (texturedata->yuv) {
GL_SetShader(data, SHADER_YV12);
GL_SetShader(data, SHADER_YUV);
} else if (texturedata->nv12) {
if (texture->format == SDL_PIXELFORMAT_NV12) {
GL_SetShader(data, SHADER_NV12);
} else {
GL_SetShader(data, SHADER_NV21);
}
} else {
GL_SetShader(data, SHADER_RGB);
}
return 0;
}
static int
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GL_ActivateRenderer(renderer);
if (GL_SetupCopy(renderer, texture) < 0) {
return -1;
}
minx = dstrect->x;
miny = dstrect->y;
@@ -1249,30 +1341,8 @@ GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
GL_ActivateRenderer(renderer);
data->glEnable(texturedata->type);
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
data->glBindTexture(texturedata->type, texturedata->vtexture);
data->glActiveTextureARB(GL_TEXTURE1_ARB);
data->glBindTexture(texturedata->type, texturedata->utexture);
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
data->glBindTexture(texturedata->type, texturedata->texture);
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);
if (GL_SetupCopy(renderer, texture) < 0) {
return -1;
}
centerx = center->x;
@@ -1361,6 +1431,7 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
format, type, temp_pixels);
if (GL_CheckError("glReadPixels()", renderer) < 0) {
SDL_free(temp_pixels);
return -1;
}
+111 -6
View File
@@ -113,7 +113,7 @@ static const char *shader_source[NUM_SHADERS][2] =
"}"
},
/* SHADER_YV12 */
/* SHADER_YUV */
{
/* vertex shader */
"varying vec4 v_color;\n"
@@ -133,7 +133,7 @@ static const char *shader_source[NUM_SHADERS][2] =
"uniform sampler2D tex2; // V \n"
"\n"
"// YUV offset \n"
"const vec3 offset = vec3(-0.0625, -0.5, -0.5);\n"
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n"
"\n"
"// RGB coefficients \n"
"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
@@ -150,7 +150,7 @@ static const char *shader_source[NUM_SHADERS][2] =
" yuv.x = texture2D(tex0, tcoord).r;\n"
"\n"
" // Get the U and V values \n"
" tcoord *= 0.5;\n"
" tcoord *= UVCoordScale;\n"
" yuv.y = texture2D(tex1, tcoord).r;\n"
" yuv.z = texture2D(tex2, tcoord).r;\n"
"\n"
@@ -162,6 +162,106 @@ static const char *shader_source[NUM_SHADERS][2] =
"\n"
" // That was easy. :) \n"
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
"}"
},
/* SHADER_NV12 */
{
/* vertex shader */
"varying vec4 v_color;\n"
"varying vec2 v_texCoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" v_color = gl_Color;\n"
" v_texCoord = vec2(gl_MultiTexCoord0);\n"
"}",
/* fragment shader */
"varying vec4 v_color;\n"
"varying vec2 v_texCoord;\n"
"uniform sampler2D tex0; // Y \n"
"uniform sampler2D tex1; // U/V \n"
"\n"
"// YUV offset \n"
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n"
"\n"
"// RGB coefficients \n"
"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
"const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n"
"const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n"
"\n"
"void main()\n"
"{\n"
" vec2 tcoord;\n"
" vec3 yuv, rgb;\n"
"\n"
" // Get the Y value \n"
" tcoord = v_texCoord;\n"
" yuv.x = texture2D(tex0, tcoord).r;\n"
"\n"
" // Get the U and V values \n"
" tcoord *= UVCoordScale;\n"
" yuv.yz = texture2D(tex1, tcoord).ra;\n"
"\n"
" // Do the color transform \n"
" yuv += offset;\n"
" rgb.r = dot(yuv, Rcoeff);\n"
" rgb.g = dot(yuv, Gcoeff);\n"
" rgb.b = dot(yuv, Bcoeff);\n"
"\n"
" // That was easy. :) \n"
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
"}"
},
/* SHADER_NV21 */
{
/* vertex shader */
"varying vec4 v_color;\n"
"varying vec2 v_texCoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" v_color = gl_Color;\n"
" v_texCoord = vec2(gl_MultiTexCoord0);\n"
"}",
/* fragment shader */
"varying vec4 v_color;\n"
"varying vec2 v_texCoord;\n"
"uniform sampler2D tex0; // Y \n"
"uniform sampler2D tex1; // U/V \n"
"\n"
"// YUV offset \n"
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n"
"\n"
"// RGB coefficients \n"
"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
"const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n"
"const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n"
"\n"
"void main()\n"
"{\n"
" vec2 tcoord;\n"
" vec3 yuv, rgb;\n"
"\n"
" // Get the Y value \n"
" tcoord = v_texCoord;\n"
" yuv.x = texture2D(tex0, tcoord).r;\n"
"\n"
" // Get the U and V values \n"
" tcoord *= UVCoordScale;\n"
" yuv.yz = texture2D(tex1, tcoord).ar;\n"
"\n"
" // Do the color transform \n"
" yuv += offset;\n"
" rgb.r = dot(yuv, Rcoeff);\n"
" rgb.g = dot(yuv, Gcoeff);\n"
" rgb.b = dot(yuv, Bcoeff);\n"
"\n"
" // That was easy. :) \n"
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
"}"
},
};
@@ -218,7 +318,11 @@ CompileShaderProgram(GL_ShaderContext *ctx, int index, GL_ShaderData *data)
if (ctx->GL_ARB_texture_rectangle_supported) {
frag_defines =
"#define sampler2D sampler2DRect\n"
"#define texture2D texture2DRect\n";
"#define texture2D texture2DRect\n"
"#define UVCoordScale 0.5\n";
} else {
frag_defines =
"#define UVCoordScale 1.0\n";
}
/* Create one program object to rule them all */
@@ -276,8 +380,9 @@ GL_CreateShaderContext()
return NULL;
}
if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
|| SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
if (!SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two") &&
(SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle"))) {
ctx->GL_ARB_texture_rectangle_supported = SDL_TRUE;
}
+3 -1
View File
@@ -26,7 +26,9 @@ typedef enum {
SHADER_NONE,
SHADER_SOLID,
SHADER_RGB,
SHADER_YV12,
SHADER_YUV,
SHADER_NV12,
SHADER_NV21,
NUM_SHADERS
} GL_Shader;
+52 -20
View File
@@ -285,42 +285,39 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
SDL_Renderer *renderer;
GLES_RenderData *data;
GLint value;
Uint32 windowFlags;
Uint32 window_flags;
int profile_mask, major, minor;
SDL_bool changed_window = SDL_FALSE;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
windowFlags = SDL_GetWindowFlags(window);
if (!(windowFlags & SDL_WINDOW_OPENGL) ||
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
changed_window = SDL_TRUE;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) {
/* Uh oh, better try to put it back... */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
SDL_RecreateWindow(window, windowFlags);
return NULL;
if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
goto error;
}
}
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
goto error;
}
data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
if (!data) {
GLES_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
goto error;
}
renderer->WindowEvent = GLES_WindowEvent;
@@ -351,16 +348,16 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
data->context = SDL_GL_CreateContext(window);
if (!data->context) {
GLES_DestroyRenderer(renderer);
return NULL;
goto error;
}
if (SDL_GL_MakeCurrent(window, data->context) < 0) {
GLES_DestroyRenderer(renderer);
return NULL;
goto error;
}
if (GLES_LoadFunctions(data) < 0) {
GLES_DestroyRenderer(renderer);
return NULL;
goto error;
}
if (flags & SDL_RENDERER_PRESENTVSYNC) {
@@ -411,6 +408,16 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
GLES_ResetState(renderer);
return renderer;
error:
if (changed_window) {
/* Uh oh, better try to put it back... */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
SDL_RecreateWindow(window, window_flags);
}
return NULL;
}
static void
@@ -684,14 +691,14 @@ static int
GLES_UpdateClipRect(SDL_Renderer * renderer)
{
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
const SDL_Rect *rect = &renderer->clip_rect;
if (SDL_CurrentContext != data->context) {
/* We'll update the clip rect after we rebind the context */
return 0;
}
if (!SDL_RectEmpty(rect)) {
if (renderer->clipping_enabled) {
const SDL_Rect *rect = &renderer->clip_rect;
data->glEnable(GL_SCISSOR_TEST);
data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
} else {
@@ -807,12 +814,24 @@ GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
int count)
{
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
GLfloat *vertices;
int idx;
GLES_SetDrawingState(renderer);
data->glVertexPointer(2, GL_FLOAT, 0, points);
data->glDrawArrays(GL_POINTS, 0, count);
/* Emit the specified vertices as points */
vertices = SDL_stack_alloc(GLfloat, count * 2);
for (idx = 0; idx < count; ++idx) {
GLfloat x = points[idx].x + 0.5f;
GLfloat y = points[idx].y + 0.5f;
vertices[idx * 2] = x;
vertices[(idx * 2) + 1] = y;
}
data->glVertexPointer(2, GL_FLOAT, 0, vertices);
data->glDrawArrays(GL_POINTS, 0, count);
SDL_stack_free(vertices);
return 0;
}
@@ -821,10 +840,22 @@ GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
int count)
{
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
GLfloat *vertices;
int idx;
GLES_SetDrawingState(renderer);
data->glVertexPointer(2, GL_FLOAT, 0, points);
/* Emit a line strip including the specified vertices */
vertices = SDL_stack_alloc(GLfloat, count * 2);
for (idx = 0; idx < count; ++idx) {
GLfloat x = points[idx].x + 0.5f;
GLfloat y = points[idx].y + 0.5f;
vertices[idx * 2] = x;
vertices[(idx * 2) + 1] = y;
}
data->glVertexPointer(2, GL_FLOAT, 0, vertices);
if (count > 2 &&
points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
/* GL_LINE_LOOP takes care of the final segment */
@@ -835,6 +866,7 @@ GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
/* We need to close the endpoint of the line */
data->glDrawArrays(GL_POINTS, count-1, 1);
}
SDL_stack_free(vertices);
return 0;
}
@@ -53,7 +53,7 @@ SDL_PROC(void, glPixelStorei, (GLenum, GLint))
SDL_PROC(void, glReadPixels, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*))
SDL_PROC(void, glScissor, (GLint, GLint, GLsizei, GLsizei))
SDL_PROC(void, glShaderBinary, (GLsizei, const GLuint *, GLenum, const void *, GLsizei))
SDL_PROC(void, glShaderSource, (GLuint, GLsizei, const char **, const GLint *))
SDL_PROC(void, glShaderSource, (GLuint, GLsizei, const GLchar* const*, const GLint *))
SDL_PROC(void, glTexImage2D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *))
SDL_PROC(void, glTexParameteri, (GLenum, GLenum, GLint))
SDL_PROC(void, glTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *))
@@ -68,4 +68,8 @@ SDL_PROC(void, glFramebufferTexture2D, (GLenum, GLenum, GLenum, GLuint, GLint))
SDL_PROC(GLenum, glCheckFramebufferStatus, (GLenum))
SDL_PROC(void, glDeleteFramebuffers, (GLsizei, const GLuint *))
SDL_PROC(GLint, glGetAttribLocation, (GLuint, const GLchar *))
SDL_PROC(void, glGetProgramInfoLog, (GLuint, GLsizei, GLsizei*, GLchar*))
SDL_PROC(void, glGenBuffers, (GLsizei, GLuint *))
SDL_PROC(void, glBindBuffer, (GLenum, GLuint))
SDL_PROC(void, glBufferData, (GLenum, GLsizeiptr, const GLvoid *, GLenum))
SDL_PROC(void, glBufferSubData, (GLenum, GLintptr, GLsizeiptr, const GLvoid *))
+427 -219
View File
@@ -28,7 +28,20 @@
#include "../../video/SDL_blit.h"
#include "SDL_shaders_gles2.h"
/* To prevent unnecessary window recreation,
/* !!! FIXME: Emscripten makes these into WebGL calls, and WebGL doesn't offer
!!! FIXME: client-side arrays (without an Emscripten compatibility hack,
!!! FIXME: at least), but the current VBO code here is dramatically
!!! FIXME: slower on actual iOS devices, even though the iOS Simulator
!!! FIXME: is okay. Some time after 2.0.4 ships, we should revisit this,
!!! FIXME: fix the performance bottleneck, and make everything use VBOs.
*/
#ifdef __EMSCRIPTEN__
#define SDL_GLES2_USE_VBOS 1
#else
#define SDL_GLES2_USE_VBOS 0
#endif
/* To prevent unnecessary window recreation,
* these should match the defaults selected in SDL_GL_ResetAttributes
*/
#define RENDERER_CONTEXT_MAJOR 2
@@ -49,10 +62,12 @@ SDL_RenderDriver GLES2_RenderDriver = {
"opengles2",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
4,
{SDL_PIXELFORMAT_ABGR8888,
{
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_BGR888},
SDL_PIXELFORMAT_BGR888
},
0,
0
}
@@ -78,7 +93,12 @@ typedef struct GLES2_TextureData
GLenum pixel_format;
GLenum pixel_type;
void *pixel_data;
size_t pitch;
int pitch;
/* YUV texture support */
SDL_bool yuv;
SDL_bool nv12;
GLenum texture_v;
GLenum texture_u;
GLES2_FBOList *fbo;
} GLES2_TextureData;
@@ -133,7 +153,9 @@ typedef enum
GLES2_UNIFORM_PROJECTION,
GLES2_UNIFORM_TEXTURE,
GLES2_UNIFORM_MODULATION,
GLES2_UNIFORM_COLOR
GLES2_UNIFORM_COLOR,
GLES2_UNIFORM_TEXTURE_U,
GLES2_UNIFORM_TEXTURE_V
} GLES2_Uniform;
typedef enum
@@ -142,7 +164,10 @@ typedef enum
GLES2_IMAGESOURCE_TEXTURE_ABGR,
GLES2_IMAGESOURCE_TEXTURE_ARGB,
GLES2_IMAGESOURCE_TEXTURE_RGB,
GLES2_IMAGESOURCE_TEXTURE_BGR
GLES2_IMAGESOURCE_TEXTURE_BGR,
GLES2_IMAGESOURCE_TEXTURE_YUV,
GLES2_IMAGESOURCE_TEXTURE_NV12,
GLES2_IMAGESOURCE_TEXTURE_NV21
} GLES2_ImageSource;
typedef struct GLES2_DriverContext
@@ -168,6 +193,11 @@ typedef struct GLES2_DriverContext
GLES2_ProgramCache program_cache;
GLES2_ProgramCacheEntry *current_program;
Uint8 clear_r, clear_g, clear_b, clear_a;
#if SDL_GLES2_USE_VBOS
GLuint vertex_buffers[4];
GLsizeiptr vertex_buffer_size[4];
#endif
} GLES2_DriverContext;
#define GLES2_MAX_CACHED_PROGRAMS 8
@@ -362,14 +392,14 @@ static int
GLES2_UpdateClipRect(SDL_Renderer * renderer)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
const SDL_Rect *rect = &renderer->clip_rect;
if (SDL_CurrentContext != data->context) {
/* We'll update the clip rect after we rebind the context */
return 0;
}
if (!SDL_RectEmpty(rect)) {
if (renderer->clipping_enabled) {
const SDL_Rect *rect = &renderer->clip_rect;
data->glEnable(GL_SCISSOR_TEST);
data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
} else {
@@ -433,6 +463,11 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
const void *pixels, int pitch);
static int GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch);
static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
void **pixels, int *pitch);
static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
@@ -465,13 +500,20 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
/* Determine the corresponding GLES texture format params */
switch (texture->format)
{
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_BGR888:
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_RGB888:
case SDL_PIXELFORMAT_BGR888:
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
break;
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_NV12:
case SDL_PIXELFORMAT_NV21:
format = GL_LUMINANCE;
type = GL_UNSIGNED_BYTE;
break;
default:
return SDL_SetError("Texture format not supported");
}
@@ -485,12 +527,26 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
data->texture_type = GL_TEXTURE_2D;
data->pixel_format = format;
data->pixel_type = type;
data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
data->texture_u = 0;
data->texture_v = 0;
scaleMode = GetScaleQuality();
/* Allocate a blob for image renderdata */
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
size_t size;
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
data->pixel_data = SDL_calloc(1, data->pitch * texture->h);
size = texture->h * data->pitch;
if (data->yuv) {
/* Need to add size for the U and V planes */
size += (2 * (texture->h * data->pitch) / 4);
}
if (data->nv12) {
/* Need to add size for the U/V plane */
size += ((texture->h * data->pitch) / 2);
}
data->pixel_data = SDL_calloc(1, size);
if (!data->pixel_data) {
SDL_free(data);
return SDL_OutOfMemory();
@@ -499,11 +555,59 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
/* Allocate the texture */
GL_CheckError("", renderer);
if (data->yuv) {
renderdata->glGenTextures(1, &data->texture_v);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
renderdata->glActiveTexture(GL_TEXTURE2);
renderdata->glBindTexture(data->texture_type, data->texture_v);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
renderdata->glTexImage2D(data->texture_type, 0, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
renderdata->glGenTextures(1, &data->texture_u);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
renderdata->glTexImage2D(data->texture_type, 0, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
return -1;
}
}
if (data->nv12) {
renderdata->glGenTextures(1, &data->texture_u);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, texture->w / 2, texture->h / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
return -1;
}
}
renderdata->glGenTextures(1, &data->texture);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
texture->driverdata = data;
renderdata->glActiveTexture(GL_TEXTURE0);
renderdata->glBindTexture(data->texture_type, data->texture);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
@@ -523,16 +627,45 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
return GL_CheckError("", renderer);
}
static int
GLES2_TexSubImage2D(GLES2_DriverContext *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
{
Uint8 *blob = NULL;
Uint8 *src;
int src_pitch;
int y;
/* Reformat the texture data into a tightly packed array */
src_pitch = width * bpp;
src = (Uint8 *)pixels;
if (pitch != src_pitch) {
blob = (Uint8 *)SDL_malloc(src_pitch * height);
if (!blob) {
return SDL_OutOfMemory();
}
src = blob;
for (y = 0; y < height; ++y)
{
SDL_memcpy(src, pixels, src_pitch);
src += src_pitch;
pixels = (Uint8 *)pixels + pitch;
}
src = blob;
}
data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
if (blob) {
SDL_free(blob);
}
return 0;
}
static int
GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
const void *pixels, int pitch)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
Uint8 *blob = NULL;
Uint8 *src;
int srcPitch;
int y;
GLES2_ActivateRenderer(renderer);
@@ -540,36 +673,113 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
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 */
data->glBindTexture(tdata->texture_type, tdata->texture);
data->glTexSubImage2D(tdata->texture_type,
0,
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x,
rect->y,
rect->w,
rect->h,
tdata->pixel_format,
tdata->pixel_type,
src);
SDL_free(blob);
pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
if (tdata->yuv) {
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
if (texture->format == SDL_PIXELFORMAT_YV12) {
data->glBindTexture(tdata->texture_type, tdata->texture_v);
} else {
data->glBindTexture(tdata->texture_type, tdata->texture_u);
}
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
rect->w / 2,
rect->h / 2,
tdata->pixel_format,
tdata->pixel_type,
pixels, pitch / 2, 1);
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
if (texture->format == SDL_PIXELFORMAT_YV12) {
data->glBindTexture(tdata->texture_type, tdata->texture_u);
} else {
data->glBindTexture(tdata->texture_type, tdata->texture_v);
}
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
rect->w / 2,
rect->h / 2,
tdata->pixel_format,
tdata->pixel_type,
pixels, pitch / 2, 1);
}
if (tdata->nv12) {
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
rect->w / 2,
rect->h / 2,
GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE,
pixels, pitch, 2);
}
return GL_CheckError("glTexSubImage2D()", renderer);
}
static int
GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
/* Bail out if we're supposed to update an empty rectangle */
if (rect->w <= 0 || rect->h <= 0)
return 0;
data->glBindTexture(tdata->texture_type, tdata->texture_v);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
rect->w / 2,
rect->h / 2,
tdata->pixel_format,
tdata->pixel_type,
Vplane, Vpitch, 1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
rect->w / 2,
rect->h / 2,
tdata->pixel_format,
tdata->pixel_type,
Uplane, Upitch, 1);
data->glBindTexture(tdata->texture_type, tdata->texture);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x,
rect->y,
rect->w,
rect->h,
tdata->pixel_format,
tdata->pixel_type,
Yplane, Ypitch, 1);
return GL_CheckError("glTexSubImage2D()", renderer);
}
@@ -638,6 +848,12 @@ GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
if (tdata)
{
data->glDeleteTextures(1, &tdata->texture);
if (tdata->texture_v) {
data->glDeleteTextures(1, &tdata->texture_v);
}
if (tdata->texture_u) {
data->glDeleteTextures(1, &tdata->texture_u);
}
SDL_free(tdata->pixel_data);
SDL_free(tdata);
texture->driverdata = NULL;
@@ -723,6 +939,10 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
/* Predetermine locations of uniform variables */
entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
data->glGetUniformLocation(entry->id, "u_projection");
entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] =
data->glGetUniformLocation(entry->id, "u_texture_v");
entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] =
data->glGetUniformLocation(entry->id, "u_texture_u");
entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
data->glGetUniformLocation(entry->id, "u_texture");
entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
@@ -734,8 +954,10 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255;
data->glUseProgram(entry->id);
data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */
data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f);
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
@@ -927,6 +1149,15 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendM
case GLES2_IMAGESOURCE_TEXTURE_BGR:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_YUV:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_NV12:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_NV21:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC;
break;
default:
goto fault;
}
@@ -1172,6 +1403,33 @@ GLES2_SetDrawingState(SDL_Renderer * renderer)
return 0;
}
static int
GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
const void *vertexData, size_t dataSizeInBytes)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
#if !SDL_GLES2_USE_VBOS
data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
#else
if (!data->vertex_buffers[attr])
data->glGenBuffers(1, &data->vertex_buffers[attr]);
data->glBindBuffer(GL_ARRAY_BUFFER, data->vertex_buffers[attr]);
if (data->vertex_buffer_size[attr] < dataSizeInBytes) {
data->glBufferData(GL_ARRAY_BUFFER, dataSizeInBytes, vertexData, GL_STREAM_DRAW);
data->vertex_buffer_size[attr] = dataSizeInBytes;
} else {
data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
}
data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
#endif
return 0;
}
static int
GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
{
@@ -1192,7 +1450,8 @@ GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int cou
vertices[idx * 2] = x;
vertices[(idx * 2) + 1] = y;
}
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
/*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
data->glDrawArrays(GL_POINTS, 0, count);
SDL_stack_free(vertices);
return 0;
@@ -1218,7 +1477,8 @@ GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int coun
vertices[idx * 2] = x;
vertices[(idx * 2) + 1] = y;
}
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
/*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
data->glDrawArrays(GL_LINE_STRIP, 0, count);
/* We need to close the endpoint of the line */
@@ -1259,27 +1519,23 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
vertices[5] = yMax;
vertices[6] = xMax;
vertices[7] = yMax;
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
/*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
return GL_CheckError("", renderer);
}
static int
GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
const SDL_FRect *dstrect)
GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
SDL_BlendMode blendMode;
GLfloat vertices[8];
GLfloat texCoords[8];
GLES2_ProgramCacheEntry *program;
Uint8 r, g, b, a;
GLES2_ActivateRenderer(renderer);
/* Activate an appropriate shader and set the projection matrix */
blendMode = texture->blendMode;
if (renderer->target) {
@@ -1287,6 +1543,18 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
if (renderer->target->format != texture->format) {
switch (texture->format)
{
case SDL_PIXELFORMAT_ARGB8888:
switch (renderer->target->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_ABGR8888:
switch (renderer->target->format)
{
@@ -1299,15 +1567,17 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
break;
}
break;
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_RGB888:
switch (renderer->target->format)
{
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_BGR888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
case SDL_PIXELFORMAT_RGB888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
case SDL_PIXELFORMAT_ARGB8888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
break;
case SDL_PIXELFORMAT_BGR888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
}
break;
@@ -1325,41 +1595,48 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
break;
}
break;
case SDL_PIXELFORMAT_RGB888:
switch (renderer->target->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;
}
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
break;
case SDL_PIXELFORMAT_NV12:
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
break;
case SDL_PIXELFORMAT_NV21:
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
break;
default:
return SDL_SetError("Unsupported texture format");
}
}
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
}
else {
} 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;
case SDL_PIXELFORMAT_ABGR8888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
break;
case SDL_PIXELFORMAT_RGB888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
break;
case SDL_PIXELFORMAT_BGR888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
break;
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
break;
case SDL_PIXELFORMAT_NV12:
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
break;
case SDL_PIXELFORMAT_NV21:
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
break;
default:
return -1;
return SDL_SetError("Unsupported texture format");
}
}
@@ -1368,6 +1645,21 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
}
/* Select the target texture */
if (tdata->yuv) {
data->glActiveTexture(GL_TEXTURE2);
data->glBindTexture(tdata->texture_type, tdata->texture_v);
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
}
if (tdata->nv12) {
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
}
data->glBindTexture(tdata->texture_type, tdata->texture);
/* Configure color modulation */
@@ -1398,6 +1690,22 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
GLES2_SetBlendMode(data, blendMode);
GLES2_SetTexCoords(data, SDL_TRUE);
return 0;
}
static int
GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
const SDL_FRect *dstrect)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
GLfloat vertices[8];
GLfloat texCoords[8];
GLES2_ActivateRenderer(renderer);
if (GLES2_SetupCopy(renderer, texture) < 0) {
return -1;
}
/* Emit the textured quad */
vertices[0] = dstrect->x;
@@ -1408,7 +1716,8 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
vertices[5] = (dstrect->y + dstrect->h);
vertices[6] = (dstrect->x + dstrect->w);
vertices[7] = (dstrect->y + dstrect->h);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
/*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
texCoords[0] = srcrect->x / (GLfloat)texture->w;
texCoords[1] = srcrect->y / (GLfloat)texture->h;
texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
@@ -1417,7 +1726,8 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
/*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
return GL_CheckError("", renderer);
@@ -1428,11 +1738,6 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
GLES2_ProgramCacheEntry *program;
Uint8 r, g, b, a;
SDL_BlendMode blendMode;
GLfloat vertices[8];
GLfloat texCoords[8];
GLfloat translate[8];
@@ -1441,6 +1746,10 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
GLES2_ActivateRenderer(renderer);
if (GLES2_SetupCopy(renderer, texture) < 0) {
return -1;
}
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
@@ -1448,124 +1757,6 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
/* Activate an appropriate shader and set the projection matrix */
blendMode = texture->blendMode;
if (renderer->target) {
/* Check if we need to do color mapping between the source and render target textures */
if (renderer->target->format != texture->format) {
switch (texture->format)
{
case SDL_PIXELFORMAT_ABGR8888:
switch (renderer->target->format)
{
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_RGB888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
case SDL_PIXELFORMAT_BGR888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
break;
}
break;
case SDL_PIXELFORMAT_ARGB8888:
switch (renderer->target->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 (renderer->target->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 (renderer->target->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;
default:
return -1;
}
}
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
return -1;
/* Select the target texture */
data->glBindTexture(tdata->texture_type, tdata->texture);
/* Configure color modulation */
/* !!! FIXME: grep for glUniform4f(), move that stuff to a subroutine, it's a lot of copy/paste. */
g = texture->g;
a = texture->a;
if (renderer->target &&
(renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
r = texture->b;
b = texture->r;
} else {
r = texture->r;
b = texture->b;
}
program = data->current_program;
if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
program->modulation_r = r;
program->modulation_g = g;
program->modulation_b = b;
program->modulation_a = a;
}
/* Configure texture blending */
GLES2_SetBlendMode(data, blendMode);
GLES2_SetTexCoords(data, SDL_TRUE);
/* Emit the textured quad */
vertices[0] = dstrect->x;
vertices[1] = dstrect->y;
@@ -1586,9 +1777,13 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
vertices[5] = vertices[7] = tmp;
}
data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
/*data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
texCoords[0] = srcrect->x / (GLfloat)texture->w;
texCoords[1] = srcrect->y / (GLfloat)texture->h;
@@ -1598,7 +1793,8 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
/*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
@@ -1743,30 +1939,27 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
#ifndef ZUNE_HD
GLboolean hasCompiler;
#endif
Uint32 windowFlags;
Uint32 window_flags;
GLint window_framebuffer;
GLint value;
int profile_mask, major, minor;
SDL_bool changed_window = SDL_FALSE;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
windowFlags = SDL_GetWindowFlags(window);
if (!(windowFlags & SDL_WINDOW_OPENGL) ||
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
changed_window = SDL_TRUE;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) {
/* Uh oh, better try to put it back... */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
SDL_RecreateWindow(window, windowFlags);
return NULL;
if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
goto error;
}
}
@@ -1774,14 +1967,14 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
goto error;
}
data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext));
if (!data) {
GLES2_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
goto error;
}
renderer->info = GLES2_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
@@ -1790,19 +1983,18 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
/* Create an OpenGL ES 2.0 context */
data->context = SDL_GL_CreateContext(window);
if (!data->context)
{
if (!data->context) {
GLES2_DestroyRenderer(renderer);
return NULL;
goto error;
}
if (SDL_GL_MakeCurrent(window, data->context) < 0) {
GLES2_DestroyRenderer(renderer);
return NULL;
goto error;
}
if (GLES2_LoadFunctions(data) < 0) {
GLES2_DestroyRenderer(renderer);
return NULL;
goto error;
}
#if __WINRT__
@@ -1850,7 +2042,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
{
GLES2_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
goto error;
}
data->shader_format_count = nFormats;
#ifdef ZUNE_HD
@@ -1869,6 +2061,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->WindowEvent = &GLES2_WindowEvent;
renderer->CreateTexture = &GLES2_CreateTexture;
renderer->UpdateTexture = &GLES2_UpdateTexture;
renderer->UpdateTextureYUV = &GLES2_UpdateTextureYUV;
renderer->LockTexture = &GLES2_LockTexture;
renderer->UnlockTexture = &GLES2_UnlockTexture;
renderer->SetRenderTarget = &GLES2_SetRenderTarget;
@@ -1887,9 +2080,24 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->GL_BindTexture = &GLES2_BindTexture;
renderer->GL_UnbindTexture = &GLES2_UnbindTexture;
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_NV12;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
GLES2_ResetState(renderer);
return renderer;
error:
if (changed_window) {
/* Uh oh, better try to put it back... */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
SDL_RecreateWindow(window, window_flags);
}
return NULL;
}
#endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
@@ -126,6 +126,74 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
} \
";
/* YUV to ABGR conversion */
static const Uint8 GLES2_FragmentSrc_TextureYUVSrc_[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform sampler2D u_texture_u; \
uniform sampler2D u_texture_v; \
uniform vec4 u_modulation; \
varying vec2 v_texCoord; \
\
void main() \
{ \
mediump vec3 yuv; \
lowp vec3 rgb; \
yuv.x = texture2D(u_texture, v_texCoord).r; \
yuv.y = texture2D(u_texture_u, v_texCoord).r - 0.5; \
yuv.z = texture2D(u_texture_v, v_texCoord).r - 0.5; \
rgb = mat3( 1, 1, 1, \
0, -0.39465, 2.03211, \
1.13983, -0.58060, 0) * yuv; \
gl_FragColor = vec4(rgb, 1); \
gl_FragColor *= u_modulation; \
} \
";
/* NV12 to ABGR conversion */
static const Uint8 GLES2_FragmentSrc_TextureNV12Src_[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform sampler2D u_texture_u; \
uniform vec4 u_modulation; \
varying vec2 v_texCoord; \
\
void main() \
{ \
mediump vec3 yuv; \
lowp vec3 rgb; \
yuv.x = texture2D(u_texture, v_texCoord).r; \
yuv.yz = texture2D(u_texture_u, v_texCoord).ra - 0.5; \
rgb = mat3( 1, 1, 1, \
0, -0.39465, 2.03211, \
1.13983, -0.58060, 0) * yuv; \
gl_FragColor = vec4(rgb, 1); \
gl_FragColor *= u_modulation; \
} \
";
/* NV21 to ABGR conversion */
static const Uint8 GLES2_FragmentSrc_TextureNV21Src_[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform sampler2D u_texture_u; \
uniform vec4 u_modulation; \
varying vec2 v_texCoord; \
\
void main() \
{ \
mediump vec3 yuv; \
lowp vec3 rgb; \
yuv.x = texture2D(u_texture, v_texCoord).r; \
yuv.yz = texture2D(u_texture_u, v_texCoord).ar - 0.5; \
rgb = mat3( 1, 1, 1, \
0, -0.39465, 2.03211, \
1.13983, -0.58060, 0) * yuv; \
gl_FragColor = vec4(rgb, 1); \
gl_FragColor *= u_modulation; \
} \
";
static const GLES2_ShaderInstance GLES2_VertexSrc_Default = {
GL_VERTEX_SHADER,
GLES2_SOURCE_SHADER,
@@ -168,6 +236,28 @@ static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureBGRSrc = {
GLES2_FragmentSrc_TextureBGRSrc_
};
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureYUVSrc = {
GL_FRAGMENT_SHADER,
GLES2_SOURCE_SHADER,
sizeof(GLES2_FragmentSrc_TextureYUVSrc_),
GLES2_FragmentSrc_TextureYUVSrc_
};
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV12Src = {
GL_FRAGMENT_SHADER,
GLES2_SOURCE_SHADER,
sizeof(GLES2_FragmentSrc_TextureNV12Src_),
GLES2_FragmentSrc_TextureNV12Src_
};
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV21Src = {
GL_FRAGMENT_SHADER,
GLES2_SOURCE_SHADER,
sizeof(GLES2_FragmentSrc_TextureNV21Src_),
GLES2_FragmentSrc_TextureNV21Src_
};
/*************************************************************************************************
* Vertex/fragment shader binaries (NVIDIA Tegra 1/2) *
*************************************************************************************************/
@@ -692,6 +782,28 @@ static GLES2_Shader GLES2_FragmentShader_Modulated_TextureBGRSrc = {
}
};
static GLES2_Shader GLES2_FragmentShader_TextureYUVSrc = {
1,
{
&GLES2_FragmentSrc_TextureYUVSrc
}
};
static GLES2_Shader GLES2_FragmentShader_TextureNV12Src = {
1,
{
&GLES2_FragmentSrc_TextureNV12Src
}
};
static GLES2_Shader GLES2_FragmentShader_TextureNV21Src = {
1,
{
&GLES2_FragmentSrc_TextureNV21Src
}
};
/*************************************************************************************************
* Shader selector *
*************************************************************************************************/
@@ -774,6 +886,21 @@ const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type, SDL_BlendMode blendMo
default:
return NULL;
}
case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC:
{
return &GLES2_FragmentShader_TextureYUVSrc;
}
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC:
{
return &GLES2_FragmentShader_TextureNV12Src;
}
case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC:
{
return &GLES2_FragmentShader_TextureNV21Src;
}
default:
return NULL;
@@ -46,7 +46,10 @@ typedef enum
GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC,
GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC,
GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC,
GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC
GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC,
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC,
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC
} GLES2_ShaderType;
#define GLES2_SOURCE_SHADER (GLenum)-1
+2 -1
View File
@@ -51,11 +51,12 @@ do { \
#define DRAW_SETPIXEL_BLEND(getpixel, setpixel) \
do { \
unsigned sr, sg, sb, sa; (void) sa; \
unsigned sr, sg, sb, sa = 0xFF; \
getpixel; \
sr = DRAW_MUL(inva, sr) + r; \
sg = DRAW_MUL(inva, sg) + g; \
sb = DRAW_MUL(inva, sb) + b; \
sa = DRAW_MUL(inva, sa) + a; \
setpixel; \
} while (0)
+9 -10
View File
@@ -82,14 +82,14 @@ SDL_RenderDriver SW_RenderDriver = {
SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
8,
{
SDL_PIXELFORMAT_RGB555,
SDL_PIXELFORMAT_RGB565,
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_RGBA8888,
SDL_PIXELFORMAT_BGRA8888,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_BGR888,
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_RGBA8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_BGRA8888
SDL_PIXELFORMAT_RGB565,
SDL_PIXELFORMAT_RGB555
},
0,
0}
@@ -146,6 +146,7 @@ SW_CreateRendererForSurface(SDL_Surface * surface)
return NULL;
}
data->surface = surface;
data->window = surface;
renderer->WindowEvent = SW_WindowEvent;
renderer->GetOutputSize = SW_GetOutputSize;
@@ -347,11 +348,9 @@ SW_UpdateClipRect(SDL_Renderer * renderer)
{
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
SDL_Surface *surface = data->surface;
const SDL_Rect *rect = &renderer->clip_rect;
if (surface) {
if (!SDL_RectEmpty(rect)) {
SDL_SetClipRect(surface, rect);
if (renderer->clipping_enabled) {
SDL_SetClipRect(surface, &renderer->clip_rect);
} else {
SDL_SetClipRect(surface, NULL);
}
+1 -1
View File
@@ -189,7 +189,7 @@ _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int
if (flipx) dx = sw - dx;
if (flipy) dy = sh - dy;
if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
sp = (tColorRGBA *)src->pixels;;
sp = (tColorRGBA *)src->pixels;
sp += ((src->pitch/4) * dy);
sp += dx;
c00 = *sp;