--- a/src/render/SDL_render.c Sat Feb 05 11:54:46 2011 -0800
+++ b/src/render/SDL_render.c Sat Feb 05 12:01:11 2011 -0800
@@ -27,7 +27,7 @@
#include "SDL_render.h"
#include "SDL_sysrender.h"
#include "../video/SDL_pixels_c.h"
-#include "software/SDL_renderer_sw_c.h"
+#include "software/SDL_render_sw_c.h"
#define CHECK_RENDERER_MAGIC(renderer, retval) \
--- a/src/render/direct3d/SDL_d3drender.c Sat Feb 05 11:54:46 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1048 +0,0 @@
-/*
- SDL - Simple DirectMedia Layer
- Copyright (C) 1997-2010 Sam Lantinga
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- Sam Lantinga
- slouken@libsdl.org
-*/
-#include "SDL_config.h"
-
-#if SDL_VIDEO_RENDER_D3D
-
-#include "../../core/windows/SDL_windows.h"
-
-#include "SDL_loadso.h"
-#include "SDL_syswm.h"
-#include "../SDL_sysrender.h"
-
-#if SDL_VIDEO_RENDER_D3D
-#define D3D_DEBUG_INFO
-#include <d3d9.h>
-#endif
-
-#ifdef ASSEMBLE_SHADER
-///////////////////////////////////////////////////////////////////////////
-// ID3DXBuffer:
-// ------------
-// The buffer object is used by D3DX to return arbitrary size data.
-//
-// GetBufferPointer -
-// Returns a pointer to the beginning of the buffer.
-//
-// GetBufferSize -
-// Returns the size of the buffer, in bytes.
-///////////////////////////////////////////////////////////////////////////
-
-typedef interface ID3DXBuffer ID3DXBuffer;
-typedef interface ID3DXBuffer *LPD3DXBUFFER;
-
-// {8BA5FB08-5195-40e2-AC58-0D989C3A0102}
-DEFINE_GUID(IID_ID3DXBuffer,
-0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
-
-#undef INTERFACE
-#define INTERFACE ID3DXBuffer
-
-typedef interface ID3DXBuffer {
- const struct ID3DXBufferVtbl FAR* lpVtbl;
-} ID3DXBuffer;
-typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
-const struct ID3DXBufferVtbl
-{
- // IUnknown
- STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
- STDMETHOD_(ULONG, AddRef)(THIS) PURE;
- STDMETHOD_(ULONG, Release)(THIS) PURE;
-
- // ID3DXBuffer
- STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
- STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
-};
-
-HRESULT WINAPI
- D3DXAssembleShader(
- LPCSTR pSrcData,
- UINT SrcDataLen,
- CONST LPVOID* pDefines,
- LPVOID pInclude,
- DWORD Flags,
- LPD3DXBUFFER* ppShader,
- LPD3DXBUFFER* ppErrorMsgs);
-
-#endif /* ASSEMBLE_SHADER */
-
-
-/* Direct3D renderer implementation */
-
-static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
-static int D3D_CreateTexture(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);
-static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch);
-static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int D3D_RenderDrawLines(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int D3D_RenderFillRects(SDL_Renderer * renderer,
- const SDL_Rect ** rects, int count);
-static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_Rect * dstrect);
-static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
- Uint32 format, void * pixels, int pitch);
-static void D3D_RenderPresent(SDL_Renderer * renderer);
-static void D3D_DestroyTexture(SDL_Renderer * renderer,
- SDL_Texture * texture);
-static void D3D_DestroyRenderer(SDL_Renderer * renderer);
-
-
-SDL_RenderDriver D3D_RenderDriver = {
- D3D_CreateRenderer,
- {
- "direct3d",
- (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
- 1,
- {SDL_PIXELFORMAT_ARGB8888},
- 0,
- 0}
-};
-
-typedef struct
-{
- void* d3dDLL;
- IDirect3D9 *d3d;
- IDirect3DDevice9 *device;
- UINT adapter;
- D3DPRESENT_PARAMETERS pparams;
- SDL_bool beginScene;
-} D3D_RenderData;
-
-typedef struct
-{
- IDirect3DTexture9 *texture;
-} D3D_TextureData;
-
-typedef struct
-{
- float x, y, z;
- float rhw;
- DWORD color;
- float u, v;
-} Vertex;
-
-static void
-D3D_SetError(const char *prefix, HRESULT result)
-{
- const char *error;
-
- switch (result) {
- case D3DERR_WRONGTEXTUREFORMAT:
- error = "WRONGTEXTUREFORMAT";
- break;
- case D3DERR_UNSUPPORTEDCOLOROPERATION:
- error = "UNSUPPORTEDCOLOROPERATION";
- break;
- case D3DERR_UNSUPPORTEDCOLORARG:
- error = "UNSUPPORTEDCOLORARG";
- break;
- case D3DERR_UNSUPPORTEDALPHAOPERATION:
- error = "UNSUPPORTEDALPHAOPERATION";
- break;
- case D3DERR_UNSUPPORTEDALPHAARG:
- error = "UNSUPPORTEDALPHAARG";
- break;
- case D3DERR_TOOMANYOPERATIONS:
- error = "TOOMANYOPERATIONS";
- break;
- case D3DERR_CONFLICTINGTEXTUREFILTER:
- error = "CONFLICTINGTEXTUREFILTER";
- break;
- case D3DERR_UNSUPPORTEDFACTORVALUE:
- error = "UNSUPPORTEDFACTORVALUE";
- break;
- case D3DERR_CONFLICTINGRENDERSTATE:
- error = "CONFLICTINGRENDERSTATE";
- break;
- case D3DERR_UNSUPPORTEDTEXTUREFILTER:
- error = "UNSUPPORTEDTEXTUREFILTER";
- break;
- case D3DERR_CONFLICTINGTEXTUREPALETTE:
- error = "CONFLICTINGTEXTUREPALETTE";
- break;
- case D3DERR_DRIVERINTERNALERROR:
- error = "DRIVERINTERNALERROR";
- break;
- case D3DERR_NOTFOUND:
- error = "NOTFOUND";
- break;
- case D3DERR_MOREDATA:
- error = "MOREDATA";
- break;
- case D3DERR_DEVICELOST:
- error = "DEVICELOST";
- break;
- case D3DERR_DEVICENOTRESET:
- error = "DEVICENOTRESET";
- break;
- case D3DERR_NOTAVAILABLE:
- error = "NOTAVAILABLE";
- break;
- case D3DERR_OUTOFVIDEOMEMORY:
- error = "OUTOFVIDEOMEMORY";
- break;
- case D3DERR_INVALIDDEVICE:
- error = "INVALIDDEVICE";
- break;
- case D3DERR_INVALIDCALL:
- error = "INVALIDCALL";
- break;
- case D3DERR_DRIVERINVALIDCALL:
- error = "DRIVERINVALIDCALL";
- break;
- case D3DERR_WASSTILLDRAWING:
- error = "WASSTILLDRAWING";
- break;
- default:
- error = "UNKNOWN";
- break;
- }
- SDL_SetError("%s: %s", prefix, error);
-}
-
-static D3DFORMAT
-PixelFormatToD3DFMT(Uint32 format)
-{
- switch (format) {
- case SDL_PIXELFORMAT_RGB565:
- return D3DFMT_R5G6B5;
- case SDL_PIXELFORMAT_RGB888:
- return D3DFMT_X8R8G8B8;
- case SDL_PIXELFORMAT_ARGB8888:
- return D3DFMT_A8R8G8B8;
- default:
- return D3DFMT_UNKNOWN;
- }
-}
-
-static Uint32
-D3DFMTToPixelFormat(D3DFORMAT format)
-{
- switch (format) {
- case D3DFMT_R5G6B5:
- return SDL_PIXELFORMAT_RGB565;
- case D3DFMT_X8R8G8B8:
- return SDL_PIXELFORMAT_RGB888;
- case D3DFMT_A8R8G8B8:
- return SDL_PIXELFORMAT_ARGB8888;
- default:
- return SDL_PIXELFORMAT_UNKNOWN;
- }
-}
-
-SDL_Renderer *
-D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
-{
- SDL_Renderer *renderer;
- D3D_RenderData *data;
- SDL_SysWMinfo windowinfo;
- HRESULT result;
- D3DPRESENT_PARAMETERS pparams;
- IDirect3DSwapChain9 *chain;
- D3DCAPS9 caps;
- Uint32 window_flags;
- int w, h;
- SDL_DisplayMode fullscreen_mode;
-
- renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
- if (!renderer) {
- SDL_OutOfMemory();
- return NULL;
- }
-
- data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- SDL_free(renderer);
- SDL_OutOfMemory();
- return NULL;
- }
-
- data->d3dDLL = SDL_LoadObject("D3D9.DLL");
- if (data->d3dDLL) {
- IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
-
- D3DCreate =
- (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL,
- "Direct3DCreate9");
- if (D3DCreate) {
- data->d3d = D3DCreate(D3D_SDK_VERSION);
- }
- if (!data->d3d) {
- SDL_UnloadObject(data->d3dDLL);
- data->d3dDLL = NULL;
- }
- }
- if (!data->d3d) {
- SDL_free(renderer);
- SDL_free(data);
- SDL_SetError("Unable to create Direct3D interface");
- return NULL;
- }
-
- renderer->CreateTexture = D3D_CreateTexture;
- renderer->UpdateTexture = D3D_UpdateTexture;
- renderer->LockTexture = D3D_LockTexture;
- renderer->UnlockTexture = D3D_UnlockTexture;
- renderer->RenderDrawPoints = D3D_RenderDrawPoints;
- renderer->RenderDrawLines = D3D_RenderDrawLines;
- renderer->RenderFillRects = D3D_RenderFillRects;
- renderer->RenderCopy = D3D_RenderCopy;
- renderer->RenderReadPixels = D3D_RenderReadPixels;
- renderer->RenderPresent = D3D_RenderPresent;
- renderer->DestroyTexture = D3D_DestroyTexture;
- renderer->DestroyRenderer = D3D_DestroyRenderer;
- renderer->info = D3D_RenderDriver.info;
- renderer->driverdata = data;
-
- renderer->info.flags = SDL_RENDERER_ACCELERATED;
-
- SDL_VERSION(&windowinfo.version);
- SDL_GetWindowWMInfo(window, &windowinfo);
-
- window_flags = SDL_GetWindowFlags(window);
- SDL_GetWindowSize(window, &w, &h);
- SDL_GetWindowDisplayMode(window, &fullscreen_mode);
-
- SDL_zero(pparams);
- 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) {
- pparams.Windowed = FALSE;
- pparams.FullScreen_RefreshRateInHz =
- fullscreen_mode.refresh_rate;
- } else {
- pparams.Windowed = TRUE;
- pparams.FullScreen_RefreshRateInHz = 0;
- }
- if (flags & SDL_RENDERER_PRESENTVSYNC) {
- pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
- } else {
- pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
- }
-
- /* FIXME: Which adapter? */
- data->adapter = D3DADAPTER_DEFAULT;
- IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
-
- result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
- D3DDEVTYPE_HAL,
- pparams.hDeviceWindow,
- (caps.
- DevCaps &
- D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
- D3DCREATE_HARDWARE_VERTEXPROCESSING :
- D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &pparams, &data->device);
- if (FAILED(result)) {
- D3D_DestroyRenderer(renderer);
- D3D_SetError("CreateDevice()", result);
- return NULL;
- }
- data->beginScene = SDL_TRUE;
-
- /* Get presentation parameters to fill info */
- result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
- if (FAILED(result)) {
- D3D_DestroyRenderer(renderer);
- D3D_SetError("GetSwapChain()", result);
- return NULL;
- }
- result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
- if (FAILED(result)) {
- IDirect3DSwapChain9_Release(chain);
- D3D_DestroyRenderer(renderer);
- D3D_SetError("GetPresentParameters()", result);
- return NULL;
- }
- IDirect3DSwapChain9_Release(chain);
- if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
- renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
- }
- data->pparams = pparams;
-
- IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
- renderer->info.max_texture_width = caps.MaxTextureWidth;
- renderer->info.max_texture_height = caps.MaxTextureHeight;
-
- /* Set up parameters for rendering */
- IDirect3DDevice9_SetVertexShader(data->device, NULL);
- IDirect3DDevice9_SetFVF(data->device,
- D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
- D3DCULL_NONE);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
- /* Enable color modulation by diffuse color */
- IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
- D3DTOP_MODULATE);
- IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
- D3DTA_TEXTURE);
- IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
- D3DTA_DIFFUSE);
- /* Enable alpha modulation by diffuse alpha */
- IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
- D3DTOP_MODULATE);
- IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
- D3DTA_TEXTURE);
- IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
- D3DTA_DIFFUSE);
- /* Disable second texture stage, since we're done */
- IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
- D3DTOP_DISABLE);
- IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
- D3DTOP_DISABLE);
-
- return renderer;
-}
-
-static int
-D3D_Reset(SDL_Renderer * renderer)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- HRESULT result;
-
- result = IDirect3DDevice9_Reset(data->device, &data->pparams);
- if (FAILED(result)) {
- if (result == D3DERR_DEVICELOST) {
- /* Don't worry about it, we'll reset later... */
- return 0;
- } else {
- D3D_SetError("Reset()", result);
- return -1;
- }
- }
- IDirect3DDevice9_SetVertexShader(data->device, NULL);
- IDirect3DDevice9_SetFVF(data->device,
- D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
- D3DCULL_NONE);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
- return 0;
-}
-
-/* FIXME: This needs to be called... when? */
-#if 0
-static int
-D3D_DisplayModeChanged(SDL_Renderer * renderer)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- SDL_Window *window = renderer->window;
- SDL_VideoDisplay *display = window->display;
-
- data->pparams.BackBufferWidth = window->w;
- data->pparams.BackBufferHeight = window->h;
- if (window->flags & SDL_WINDOW_FULLSCREEN) {
- data->pparams.BackBufferFormat =
- PixelFormatToD3DFMT(window->fullscreen_mode.format);
- } else {
- data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
- }
- return D3D_Reset(renderer);
-}
-#endif
-
-static int
-D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
- SDL_Window *window = renderer->window;
- D3DFORMAT display_format = renderdata->pparams.BackBufferFormat;
- D3D_TextureData *data;
- D3DPOOL pool;
- DWORD usage;
- HRESULT result;
-
- data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- SDL_OutOfMemory();
- return -1;
- }
-
- texture->driverdata = data;
-
-#ifdef USE_DYNAMIC_TEXTURE
- if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
- pool = D3DPOOL_DEFAULT;
- usage = D3DUSAGE_DYNAMIC;
- } else
-#endif
- {
- pool = D3DPOOL_MANAGED;
- usage = 0;
- }
-
- result =
- IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
- texture->h, 1, usage,
- PixelFormatToD3DFMT(texture->format),
- pool, &data->texture, NULL);
- if (FAILED(result)) {
- D3D_SetError("CreateTexture()", result);
- 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;
- D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
- RECT d3drect;
- D3DLOCKED_RECT locked;
- const Uint8 *src;
- Uint8 *dst;
- int row, length;
- HRESULT result;
-
-#ifdef USE_DYNAMIC_TEXTURE
- if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
- rect->x == 0 && rect->y == 0 &&
- rect->w == texture->w && rect->h == texture->h) {
- result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
- } else
-#endif
- {
- 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);
- }
-
- if (FAILED(result)) {
- D3D_SetError("LockRect()", result);
- return -1;
- }
-
- src = pixels;
- dst = locked.pBits;
- length = rect->w * SDL_BYTESPERPIXEL(texture->format);
- if (length == pitch && length == locked.Pitch) {
- SDL_memcpy(dst, src, length*rect->h);
- } else {
- for (row = 0; row < rect->h; ++row) {
- SDL_memcpy(dst, src, length);
- src += pitch;
- dst += locked.Pitch;
- }
- }
- IDirect3DTexture9_UnlockRect(data->texture, 0);
-
- return 0;
-}
-
-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;
-
- 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);
- if (FAILED(result)) {
- D3D_SetError("LockRect()", result);
- return -1;
- }
- *pixels = locked.pBits;
- *pitch = locked.Pitch;
- return 0;
-}
-
-static void
-D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-
- IDirect3DTexture9_UnlockRect(data->texture, 0);
-}
-
-static void
-D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
-{
- switch (blendMode) {
- case SDL_BLENDMODE_NONE:
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
- FALSE);
- break;
- case SDL_BLENDMODE_BLEND:
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
- TRUE);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
- D3DBLEND_SRCALPHA);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
- D3DBLEND_INVSRCALPHA);
- break;
- case SDL_BLENDMODE_ADD:
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
- TRUE);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
- D3DBLEND_SRCALPHA);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
- D3DBLEND_ONE);
- break;
- case SDL_BLENDMODE_MOD:
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
- TRUE);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
- D3DBLEND_ZERO);
- IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
- D3DBLEND_SRCCOLOR);
- break;
- }
-}
-
-static int
-D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- DWORD color;
- Vertex *vertices;
- int i;
- HRESULT result;
-
- if (data->beginScene) {
- IDirect3DDevice9_BeginScene(data->device);
- data->beginScene = SDL_FALSE;
- }
-
- D3D_SetBlendMode(data, renderer->blendMode);
-
- result =
- IDirect3DDevice9_SetTexture(data->device, 0,
- (IDirect3DBaseTexture9 *) 0);
- if (FAILED(result)) {
- D3D_SetError("SetTexture()", result);
- return -1;
- }
-
- color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
-
- vertices = SDL_stack_alloc(Vertex, count);
- for (i = 0; i < count; ++i) {
- vertices[i].x = (float) points[i].x;
- vertices[i].y = (float) points[i].y;
- vertices[i].z = 0.0f;
- vertices[i].rhw = 1.0f;
- vertices[i].color = color;
- vertices[i].u = 0.0f;
- vertices[i].v = 0.0f;
- }
- result =
- IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
- vertices, sizeof(*vertices));
- SDL_stack_free(vertices);
- if (FAILED(result)) {
- D3D_SetError("DrawPrimitiveUP()", result);
- return -1;
- }
- return 0;
-}
-
-static int
-D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- DWORD color;
- Vertex *vertices;
- int i;
- HRESULT result;
-
- if (data->beginScene) {
- IDirect3DDevice9_BeginScene(data->device);
- data->beginScene = SDL_FALSE;
- }
-
- D3D_SetBlendMode(data, renderer->blendMode);
-
- result =
- IDirect3DDevice9_SetTexture(data->device, 0,
- (IDirect3DBaseTexture9 *) 0);
- if (FAILED(result)) {
- D3D_SetError("SetTexture()", result);
- return -1;
- }
-
- color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
-
- vertices = SDL_stack_alloc(Vertex, count);
- for (i = 0; i < count; ++i) {
- vertices[i].x = (float) points[i].x;
- vertices[i].y = (float) points[i].y;
- vertices[i].z = 0.0f;
- vertices[i].rhw = 1.0f;
- vertices[i].color = color;
- vertices[i].u = 0.0f;
- vertices[i].v = 0.0f;
- }
- result =
- IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
- vertices, sizeof(*vertices));
-
- /* DirectX 9 has the same line rasterization semantics as GDI,
- so we need to close the endpoint of the line */
- if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
- vertices[0].x = (float) points[count-1].x;
- vertices[0].y = (float) points[count-1].y;
- result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
- }
-
- SDL_stack_free(vertices);
- if (FAILED(result)) {
- D3D_SetError("DrawPrimitiveUP()", result);
- return -1;
- }
- return 0;
-}
-
-static int
-D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
- int count)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- DWORD color;
- int i;
- float minx, miny, maxx, maxy;
- Vertex vertices[4];
- HRESULT result;
-
- if (data->beginScene) {
- IDirect3DDevice9_BeginScene(data->device);
- data->beginScene = SDL_FALSE;
- }
-
- D3D_SetBlendMode(data, renderer->blendMode);
-
- result =
- IDirect3DDevice9_SetTexture(data->device, 0,
- (IDirect3DBaseTexture9 *) 0);
- if (FAILED(result)) {
- D3D_SetError("SetTexture()", result);
- return -1;
- }
-
- color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
-
- for (i = 0; i < count; ++i) {
- const SDL_Rect *rect = rects[i];
-
- minx = (float) rect->x;
- miny = (float) rect->y;
- maxx = (float) rect->x + rect->w;
- maxy = (float) rect->y + rect->h;
-
- vertices[0].x = minx;
- vertices[0].y = miny;
- vertices[0].z = 0.0f;
- vertices[0].rhw = 1.0f;
- vertices[0].color = color;
- vertices[0].u = 0.0f;
- vertices[0].v = 0.0f;
-
- vertices[1].x = maxx;
- vertices[1].y = miny;
- vertices[1].z = 0.0f;
- vertices[1].rhw = 1.0f;
- vertices[1].color = color;
- vertices[1].u = 0.0f;
- vertices[1].v = 0.0f;
-
- vertices[2].x = maxx;
- vertices[2].y = maxy;
- vertices[2].z = 0.0f;
- vertices[2].rhw = 1.0f;
- vertices[2].color = color;
- vertices[2].u = 0.0f;
- vertices[2].v = 0.0f;
-
- vertices[3].x = minx;
- vertices[3].y = maxy;
- vertices[3].z = 0.0f;
- vertices[3].rhw = 1.0f;
- vertices[3].color = color;
- vertices[3].u = 0.0f;
- vertices[3].v = 0.0f;
-
- result =
- IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
- 2, vertices, sizeof(*vertices));
- if (FAILED(result)) {
- D3D_SetError("DrawPrimitiveUP()", result);
- return -1;
- }
- }
- return 0;
-}
-
-static int
-D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_Rect * dstrect)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
- LPDIRECT3DPIXELSHADER9 shader = NULL;
- float minx, miny, maxx, maxy;
- float minu, maxu, minv, maxv;
- DWORD color;
- Vertex vertices[4];
- HRESULT result;
-
- if (data->beginScene) {
- IDirect3DDevice9_BeginScene(data->device);
- data->beginScene = SDL_FALSE;
- }
-
- minx = (float) dstrect->x - 0.5f;
- miny = (float) dstrect->y - 0.5f;
- maxx = (float) dstrect->x + dstrect->w - 0.5f;
- maxy = (float) dstrect->y + dstrect->h - 0.5f;
-
- minu = (float) srcrect->x / texture->w;
- maxu = (float) (srcrect->x + srcrect->w) / texture->w;
- minv = (float) srcrect->y / texture->h;
- maxv = (float) (srcrect->y + srcrect->h) / texture->h;
-
- color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
-
- vertices[0].x = minx;
- vertices[0].y = miny;
- vertices[0].z = 0.0f;
- vertices[0].rhw = 1.0f;
- vertices[0].color = color;
- vertices[0].u = minu;
- vertices[0].v = minv;
-
- vertices[1].x = maxx;
- vertices[1].y = miny;
- vertices[1].z = 0.0f;
- vertices[1].rhw = 1.0f;
- vertices[1].color = color;
- vertices[1].u = maxu;
- vertices[1].v = minv;
-
- vertices[2].x = maxx;
- vertices[2].y = maxy;
- vertices[2].z = 0.0f;
- vertices[2].rhw = 1.0f;
- vertices[2].color = color;
- vertices[2].u = maxu;
- vertices[2].v = maxv;
-
- vertices[3].x = minx;
- vertices[3].y = maxy;
- vertices[3].z = 0.0f;
- vertices[3].rhw = 1.0f;
- vertices[3].color = color;
- vertices[3].u = minu;
- vertices[3].v = maxv;
-
- D3D_SetBlendMode(data, texture->blendMode);
-
- IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
- D3DTEXF_LINEAR);
- IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
- D3DTEXF_LINEAR);
-
- result =
- IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
- texturedata->texture);
- if (FAILED(result)) {
- D3D_SetError("SetTexture()", result);
- return -1;
- }
- if (shader) {
- result = IDirect3DDevice9_SetPixelShader(data->device, shader);
- if (FAILED(result)) {
- D3D_SetError("SetShader()", result);
- return -1;
- }
- }
- result =
- IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
- vertices, sizeof(*vertices));
- if (FAILED(result)) {
- D3D_SetError("DrawPrimitiveUP()", result);
- return -1;
- }
- if (shader) {
- result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
- if (FAILED(result)) {
- D3D_SetError("SetShader()", result);
- return -1;
- }
- }
- return 0;
-}
-
-static int
-D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
- Uint32 format, void * pixels, int pitch)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- D3DSURFACE_DESC desc;
- LPDIRECT3DSURFACE9 backBuffer;
- LPDIRECT3DSURFACE9 surface;
- RECT d3drect;
- D3DLOCKED_RECT locked;
- HRESULT result;
-
- result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
- if (FAILED(result)) {
- D3D_SetError("GetBackBuffer()", result);
- return -1;
- }
-
- result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
- if (FAILED(result)) {
- D3D_SetError("GetDesc()", result);
- IDirect3DSurface9_Release(backBuffer);
- return -1;
- }
-
- result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
- if (FAILED(result)) {
- D3D_SetError("CreateOffscreenPlainSurface()", result);
- IDirect3DSurface9_Release(backBuffer);
- return -1;
- }
-
- result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
- if (FAILED(result)) {
- D3D_SetError("GetRenderTargetData()", result);
- IDirect3DSurface9_Release(surface);
- IDirect3DSurface9_Release(backBuffer);
- return -1;
- }
-
- d3drect.left = rect->x;
- d3drect.right = rect->x + rect->w;
- d3drect.top = rect->y;
- d3drect.bottom = rect->y + rect->h;
-
- result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
- if (FAILED(result)) {
- D3D_SetError("LockRect()", result);
- IDirect3DSurface9_Release(surface);
- IDirect3DSurface9_Release(backBuffer);
- return -1;
- }
-
- SDL_ConvertPixels(rect->w, rect->h,
- D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
- format, pixels, pitch);
-
- IDirect3DSurface9_UnlockRect(surface);
-
- IDirect3DSurface9_Release(surface);
- IDirect3DSurface9_Release(backBuffer);
-
- return 0;
-}
-
-static void
-D3D_RenderPresent(SDL_Renderer * renderer)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
- HRESULT result;
-
- if (!data->beginScene) {
- IDirect3DDevice9_EndScene(data->device);
- data->beginScene = SDL_TRUE;
- }
-
- result = IDirect3DDevice9_TestCooperativeLevel(data->device);
- if (result == D3DERR_DEVICELOST) {
- /* We'll reset later */
- return;
- }
- if (result == D3DERR_DEVICENOTRESET) {
- D3D_Reset(renderer);
- }
- result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
- if (FAILED(result)) {
- D3D_SetError("Present()", result);
- }
-}
-
-static void
-D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
-
- if (!data) {
- return;
- }
- if (data->texture) {
- IDirect3DTexture9_Release(data->texture);
- }
- SDL_free(data);
- texture->driverdata = NULL;
-}
-
-static void
-D3D_DestroyRenderer(SDL_Renderer * renderer)
-{
- D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
-
- if (data) {
- if (data->device) {
- IDirect3DDevice9_Release(data->device);
- }
- if (data->d3d) {
- IDirect3D9_Release(data->d3d);
- SDL_UnloadObject(data->d3dDLL);
- }
- SDL_free(data);
- }
- SDL_free(renderer);
-}
-
-#endif /* SDL_VIDEO_RENDER_D3D */
-
-/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/render/direct3d/SDL_render_d3d.c Sat Feb 05 12:01:11 2011 -0800
@@ -0,0 +1,1048 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2010 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#if SDL_VIDEO_RENDER_D3D
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "SDL_loadso.h"
+#include "SDL_syswm.h"
+#include "../SDL_sysrender.h"
+
+#if SDL_VIDEO_RENDER_D3D
+#define D3D_DEBUG_INFO
+#include <d3d9.h>
+#endif
+
+#ifdef ASSEMBLE_SHADER
+///////////////////////////////////////////////////////////////////////////
+// ID3DXBuffer:
+// ------------
+// The buffer object is used by D3DX to return arbitrary size data.
+//
+// GetBufferPointer -
+// Returns a pointer to the beginning of the buffer.
+//
+// GetBufferSize -
+// Returns the size of the buffer, in bytes.
+///////////////////////////////////////////////////////////////////////////
+
+typedef interface ID3DXBuffer ID3DXBuffer;
+typedef interface ID3DXBuffer *LPD3DXBUFFER;
+
+// {8BA5FB08-5195-40e2-AC58-0D989C3A0102}
+DEFINE_GUID(IID_ID3DXBuffer,
+0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
+
+#undef INTERFACE
+#define INTERFACE ID3DXBuffer
+
+typedef interface ID3DXBuffer {
+ const struct ID3DXBufferVtbl FAR* lpVtbl;
+} ID3DXBuffer;
+typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
+const struct ID3DXBufferVtbl
+{
+ // IUnknown
+ STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
+ STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG, Release)(THIS) PURE;
+
+ // ID3DXBuffer
+ STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
+ STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
+};
+
+HRESULT WINAPI
+ D3DXAssembleShader(
+ LPCSTR pSrcData,
+ UINT SrcDataLen,
+ CONST LPVOID* pDefines,
+ LPVOID pInclude,
+ DWORD Flags,
+ LPD3DXBUFFER* ppShader,
+ LPD3DXBUFFER* ppErrorMsgs);
+
+#endif /* ASSEMBLE_SHADER */
+
+
+/* Direct3D renderer implementation */
+
+static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
+static int D3D_CreateTexture(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);
+static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch);
+static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int D3D_RenderDrawLines(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int D3D_RenderFillRects(SDL_Renderer * renderer,
+ const SDL_Rect ** rects, int count);
+static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+ Uint32 format, void * pixels, int pitch);
+static void D3D_RenderPresent(SDL_Renderer * renderer);
+static void D3D_DestroyTexture(SDL_Renderer * renderer,
+ SDL_Texture * texture);
+static void D3D_DestroyRenderer(SDL_Renderer * renderer);
+
+
+SDL_RenderDriver D3D_RenderDriver = {
+ D3D_CreateRenderer,
+ {
+ "direct3d",
+ (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
+ 1,
+ {SDL_PIXELFORMAT_ARGB8888},
+ 0,
+ 0}
+};
+
+typedef struct
+{
+ void* d3dDLL;
+ IDirect3D9 *d3d;
+ IDirect3DDevice9 *device;
+ UINT adapter;
+ D3DPRESENT_PARAMETERS pparams;
+ SDL_bool beginScene;
+} D3D_RenderData;
+
+typedef struct
+{
+ IDirect3DTexture9 *texture;
+} D3D_TextureData;
+
+typedef struct
+{
+ float x, y, z;
+ float rhw;
+ DWORD color;
+ float u, v;
+} Vertex;
+
+static void
+D3D_SetError(const char *prefix, HRESULT result)
+{
+ const char *error;
+
+ switch (result) {
+ case D3DERR_WRONGTEXTUREFORMAT:
+ error = "WRONGTEXTUREFORMAT";
+ break;
+ case D3DERR_UNSUPPORTEDCOLOROPERATION:
+ error = "UNSUPPORTEDCOLOROPERATION";
+ break;
+ case D3DERR_UNSUPPORTEDCOLORARG:
+ error = "UNSUPPORTEDCOLORARG";
+ break;
+ case D3DERR_UNSUPPORTEDALPHAOPERATION:
+ error = "UNSUPPORTEDALPHAOPERATION";
+ break;
+ case D3DERR_UNSUPPORTEDALPHAARG:
+ error = "UNSUPPORTEDALPHAARG";
+ break;
+ case D3DERR_TOOMANYOPERATIONS:
+ error = "TOOMANYOPERATIONS";
+ break;
+ case D3DERR_CONFLICTINGTEXTUREFILTER:
+ error = "CONFLICTINGTEXTUREFILTER";
+ break;
+ case D3DERR_UNSUPPORTEDFACTORVALUE:
+ error = "UNSUPPORTEDFACTORVALUE";
+ break;
+ case D3DERR_CONFLICTINGRENDERSTATE:
+ error = "CONFLICTINGRENDERSTATE";
+ break;
+ case D3DERR_UNSUPPORTEDTEXTUREFILTER:
+ error = "UNSUPPORTEDTEXTUREFILTER";
+ break;
+ case D3DERR_CONFLICTINGTEXTUREPALETTE:
+ error = "CONFLICTINGTEXTUREPALETTE";
+ break;
+ case D3DERR_DRIVERINTERNALERROR:
+ error = "DRIVERINTERNALERROR";
+ break;
+ case D3DERR_NOTFOUND:
+ error = "NOTFOUND";
+ break;
+ case D3DERR_MOREDATA:
+ error = "MOREDATA";
+ break;
+ case D3DERR_DEVICELOST:
+ error = "DEVICELOST";
+ break;
+ case D3DERR_DEVICENOTRESET:
+ error = "DEVICENOTRESET";
+ break;
+ case D3DERR_NOTAVAILABLE:
+ error = "NOTAVAILABLE";
+ break;
+ case D3DERR_OUTOFVIDEOMEMORY:
+ error = "OUTOFVIDEOMEMORY";
+ break;
+ case D3DERR_INVALIDDEVICE:
+ error = "INVALIDDEVICE";
+ break;
+ case D3DERR_INVALIDCALL:
+ error = "INVALIDCALL";
+ break;
+ case D3DERR_DRIVERINVALIDCALL:
+ error = "DRIVERINVALIDCALL";
+ break;
+ case D3DERR_WASSTILLDRAWING:
+ error = "WASSTILLDRAWING";
+ break;
+ default:
+ error = "UNKNOWN";
+ break;
+ }
+ SDL_SetError("%s: %s", prefix, error);
+}
+
+static D3DFORMAT
+PixelFormatToD3DFMT(Uint32 format)
+{
+ switch (format) {
+ case SDL_PIXELFORMAT_RGB565:
+ return D3DFMT_R5G6B5;
+ case SDL_PIXELFORMAT_RGB888:
+ return D3DFMT_X8R8G8B8;
+ case SDL_PIXELFORMAT_ARGB8888:
+ return D3DFMT_A8R8G8B8;
+ default:
+ return D3DFMT_UNKNOWN;
+ }
+}
+
+static Uint32
+D3DFMTToPixelFormat(D3DFORMAT format)
+{
+ switch (format) {
+ case D3DFMT_R5G6B5:
+ return SDL_PIXELFORMAT_RGB565;
+ case D3DFMT_X8R8G8B8:
+ return SDL_PIXELFORMAT_RGB888;
+ case D3DFMT_A8R8G8B8:
+ return SDL_PIXELFORMAT_ARGB8888;
+ default:
+ return SDL_PIXELFORMAT_UNKNOWN;
+ }
+}
+
+SDL_Renderer *
+D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+ SDL_Renderer *renderer;
+ D3D_RenderData *data;
+ SDL_SysWMinfo windowinfo;
+ HRESULT result;
+ D3DPRESENT_PARAMETERS pparams;
+ IDirect3DSwapChain9 *chain;
+ D3DCAPS9 caps;
+ Uint32 window_flags;
+ int w, h;
+ SDL_DisplayMode fullscreen_mode;
+
+ renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+ if (!renderer) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ SDL_free(renderer);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ data->d3dDLL = SDL_LoadObject("D3D9.DLL");
+ if (data->d3dDLL) {
+ IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
+
+ D3DCreate =
+ (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL,
+ "Direct3DCreate9");
+ if (D3DCreate) {
+ data->d3d = D3DCreate(D3D_SDK_VERSION);
+ }
+ if (!data->d3d) {
+ SDL_UnloadObject(data->d3dDLL);
+ data->d3dDLL = NULL;
+ }
+ }
+ if (!data->d3d) {
+ SDL_free(renderer);
+ SDL_free(data);
+ SDL_SetError("Unable to create Direct3D interface");
+ return NULL;
+ }
+
+ renderer->CreateTexture = D3D_CreateTexture;
+ renderer->UpdateTexture = D3D_UpdateTexture;
+ renderer->LockTexture = D3D_LockTexture;
+ renderer->UnlockTexture = D3D_UnlockTexture;
+ renderer->RenderDrawPoints = D3D_RenderDrawPoints;
+ renderer->RenderDrawLines = D3D_RenderDrawLines;
+ renderer->RenderFillRects = D3D_RenderFillRects;
+ renderer->RenderCopy = D3D_RenderCopy;
+ renderer->RenderReadPixels = D3D_RenderReadPixels;
+ renderer->RenderPresent = D3D_RenderPresent;
+ renderer->DestroyTexture = D3D_DestroyTexture;
+ renderer->DestroyRenderer = D3D_DestroyRenderer;
+ renderer->info = D3D_RenderDriver.info;
+ renderer->driverdata = data;
+
+ renderer->info.flags = SDL_RENDERER_ACCELERATED;
+
+ SDL_VERSION(&windowinfo.version);
+ SDL_GetWindowWMInfo(window, &windowinfo);
+
+ window_flags = SDL_GetWindowFlags(window);
+ SDL_GetWindowSize(window, &w, &h);
+ SDL_GetWindowDisplayMode(window, &fullscreen_mode);
+
+ SDL_zero(pparams);
+ 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) {
+ pparams.Windowed = FALSE;
+ pparams.FullScreen_RefreshRateInHz =
+ fullscreen_mode.refresh_rate;
+ } else {
+ pparams.Windowed = TRUE;
+ pparams.FullScreen_RefreshRateInHz = 0;
+ }
+ if (flags & SDL_RENDERER_PRESENTVSYNC) {
+ pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+
+ /* FIXME: Which adapter? */
+ data->adapter = D3DADAPTER_DEFAULT;
+ IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
+
+ result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
+ D3DDEVTYPE_HAL,
+ pparams.hDeviceWindow,
+ (caps.
+ DevCaps &
+ D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
+ D3DCREATE_HARDWARE_VERTEXPROCESSING :
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING,
+ &pparams, &data->device);
+ if (FAILED(result)) {
+ D3D_DestroyRenderer(renderer);
+ D3D_SetError("CreateDevice()", result);
+ return NULL;
+ }
+ data->beginScene = SDL_TRUE;
+
+ /* Get presentation parameters to fill info */
+ result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
+ if (FAILED(result)) {
+ D3D_DestroyRenderer(renderer);
+ D3D_SetError("GetSwapChain()", result);
+ return NULL;
+ }
+ result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
+ if (FAILED(result)) {
+ IDirect3DSwapChain9_Release(chain);
+ D3D_DestroyRenderer(renderer);
+ D3D_SetError("GetPresentParameters()", result);
+ return NULL;
+ }
+ IDirect3DSwapChain9_Release(chain);
+ if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
+ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+ }
+ data->pparams = pparams;
+
+ IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
+ renderer->info.max_texture_width = caps.MaxTextureWidth;
+ renderer->info.max_texture_height = caps.MaxTextureHeight;
+
+ /* Set up parameters for rendering */
+ IDirect3DDevice9_SetVertexShader(data->device, NULL);
+ IDirect3DDevice9_SetFVF(data->device,
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
+ D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
+ /* Enable color modulation by diffuse color */
+ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
+ D3DTOP_MODULATE);
+ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
+ D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
+ D3DTA_DIFFUSE);
+ /* Enable alpha modulation by diffuse alpha */
+ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
+ D3DTOP_MODULATE);
+ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
+ D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
+ D3DTA_DIFFUSE);
+ /* Disable second texture stage, since we're done */
+ IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
+ D3DTOP_DISABLE);
+ IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
+ D3DTOP_DISABLE);
+
+ return renderer;
+}
+
+static int
+D3D_Reset(SDL_Renderer * renderer)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ HRESULT result;
+
+ result = IDirect3DDevice9_Reset(data->device, &data->pparams);
+ if (FAILED(result)) {
+ if (result == D3DERR_DEVICELOST) {
+ /* Don't worry about it, we'll reset later... */
+ return 0;
+ } else {
+ D3D_SetError("Reset()", result);
+ return -1;
+ }
+ }
+ IDirect3DDevice9_SetVertexShader(data->device, NULL);
+ IDirect3DDevice9_SetFVF(data->device,
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
+ D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
+ return 0;
+}
+
+/* FIXME: This needs to be called... when? */
+#if 0
+static int
+D3D_DisplayModeChanged(SDL_Renderer * renderer)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ SDL_Window *window = renderer->window;
+ SDL_VideoDisplay *display = window->display;
+
+ data->pparams.BackBufferWidth = window->w;
+ data->pparams.BackBufferHeight = window->h;
+ if (window->flags & SDL_WINDOW_FULLSCREEN) {
+ data->pparams.BackBufferFormat =
+ PixelFormatToD3DFMT(window->fullscreen_mode.format);
+ } else {
+ data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
+ }
+ return D3D_Reset(renderer);
+}
+#endif
+
+static int
+D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
+ SDL_Window *window = renderer->window;
+ D3DFORMAT display_format = renderdata->pparams.BackBufferFormat;
+ D3D_TextureData *data;
+ D3DPOOL pool;
+ DWORD usage;
+ HRESULT result;
+
+ data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ SDL_OutOfMemory();
+ return -1;
+ }
+
+ texture->driverdata = data;
+
+#ifdef USE_DYNAMIC_TEXTURE
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ pool = D3DPOOL_DEFAULT;
+ usage = D3DUSAGE_DYNAMIC;
+ } else
+#endif
+ {
+ pool = D3DPOOL_MANAGED;
+ usage = 0;
+ }
+
+ result =
+ IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
+ texture->h, 1, usage,
+ PixelFormatToD3DFMT(texture->format),
+ pool, &data->texture, NULL);
+ if (FAILED(result)) {
+ D3D_SetError("CreateTexture()", result);
+ 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;
+ D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
+ RECT d3drect;
+ D3DLOCKED_RECT locked;
+ const Uint8 *src;
+ Uint8 *dst;
+ int row, length;
+ HRESULT result;
+
+#ifdef USE_DYNAMIC_TEXTURE
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
+ rect->x == 0 && rect->y == 0 &&
+ rect->w == texture->w && rect->h == texture->h) {
+ result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
+ } else
+#endif
+ {
+ 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);
+ }
+
+ if (FAILED(result)) {
+ D3D_SetError("LockRect()", result);
+ return -1;
+ }
+
+ src = pixels;
+ dst = locked.pBits;
+ length = rect->w * SDL_BYTESPERPIXEL(texture->format);
+ if (length == pitch && length == locked.Pitch) {
+ SDL_memcpy(dst, src, length*rect->h);
+ } else {
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, src, length);
+ src += pitch;
+ dst += locked.Pitch;
+ }
+ }
+ IDirect3DTexture9_UnlockRect(data->texture, 0);
+
+ return 0;
+}
+
+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;
+
+ 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);
+ if (FAILED(result)) {
+ D3D_SetError("LockRect()", result);
+ return -1;
+ }
+ *pixels = locked.pBits;
+ *pitch = locked.Pitch;
+ return 0;
+}
+
+static void
+D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
+
+ IDirect3DTexture9_UnlockRect(data->texture, 0);
+}
+
+static void
+D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
+{
+ switch (blendMode) {
+ case SDL_BLENDMODE_NONE:
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
+ FALSE);
+ break;
+ case SDL_BLENDMODE_BLEND:
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
+ TRUE);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
+ D3DBLEND_SRCALPHA);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
+ D3DBLEND_INVSRCALPHA);
+ break;
+ case SDL_BLENDMODE_ADD:
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
+ TRUE);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
+ D3DBLEND_SRCALPHA);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
+ D3DBLEND_ONE);
+ break;
+ case SDL_BLENDMODE_MOD:
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
+ TRUE);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
+ D3DBLEND_ZERO);
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
+ D3DBLEND_SRCCOLOR);
+ break;
+ }
+}
+
+static int
+D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ DWORD color;
+ Vertex *vertices;
+ int i;
+ HRESULT result;
+
+ if (data->beginScene) {
+ IDirect3DDevice9_BeginScene(data->device);
+ data->beginScene = SDL_FALSE;
+ }
+
+ D3D_SetBlendMode(data, renderer->blendMode);
+
+ result =
+ IDirect3DDevice9_SetTexture(data->device, 0,
+ (IDirect3DBaseTexture9 *) 0);
+ if (FAILED(result)) {
+ D3D_SetError("SetTexture()", result);
+ return -1;
+ }
+
+ color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
+
+ vertices = SDL_stack_alloc(Vertex, count);
+ for (i = 0; i < count; ++i) {
+ vertices[i].x = (float) points[i].x;
+ vertices[i].y = (float) points[i].y;
+ vertices[i].z = 0.0f;
+ vertices[i].rhw = 1.0f;
+ vertices[i].color = color;
+ vertices[i].u = 0.0f;
+ vertices[i].v = 0.0f;
+ }
+ result =
+ IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
+ vertices, sizeof(*vertices));
+ SDL_stack_free(vertices);
+ if (FAILED(result)) {
+ D3D_SetError("DrawPrimitiveUP()", result);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ DWORD color;
+ Vertex *vertices;
+ int i;
+ HRESULT result;
+
+ if (data->beginScene) {
+ IDirect3DDevice9_BeginScene(data->device);
+ data->beginScene = SDL_FALSE;
+ }
+
+ D3D_SetBlendMode(data, renderer->blendMode);
+
+ result =
+ IDirect3DDevice9_SetTexture(data->device, 0,
+ (IDirect3DBaseTexture9 *) 0);
+ if (FAILED(result)) {
+ D3D_SetError("SetTexture()", result);
+ return -1;
+ }
+
+ color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
+
+ vertices = SDL_stack_alloc(Vertex, count);
+ for (i = 0; i < count; ++i) {
+ vertices[i].x = (float) points[i].x;
+ vertices[i].y = (float) points[i].y;
+ vertices[i].z = 0.0f;
+ vertices[i].rhw = 1.0f;
+ vertices[i].color = color;
+ vertices[i].u = 0.0f;
+ vertices[i].v = 0.0f;
+ }
+ result =
+ IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
+ vertices, sizeof(*vertices));
+
+ /* DirectX 9 has the same line rasterization semantics as GDI,
+ so we need to close the endpoint of the line */
+ if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
+ vertices[0].x = (float) points[count-1].x;
+ vertices[0].y = (float) points[count-1].y;
+ result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
+ }
+
+ SDL_stack_free(vertices);
+ if (FAILED(result)) {
+ D3D_SetError("DrawPrimitiveUP()", result);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+ int count)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ DWORD color;
+ int i;
+ float minx, miny, maxx, maxy;
+ Vertex vertices[4];
+ HRESULT result;
+
+ if (data->beginScene) {
+ IDirect3DDevice9_BeginScene(data->device);
+ data->beginScene = SDL_FALSE;
+ }
+
+ D3D_SetBlendMode(data, renderer->blendMode);
+
+ result =
+ IDirect3DDevice9_SetTexture(data->device, 0,
+ (IDirect3DBaseTexture9 *) 0);
+ if (FAILED(result)) {
+ D3D_SetError("SetTexture()", result);
+ return -1;
+ }
+
+ color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
+
+ for (i = 0; i < count; ++i) {
+ const SDL_Rect *rect = rects[i];
+
+ minx = (float) rect->x;
+ miny = (float) rect->y;
+ maxx = (float) rect->x + rect->w;
+ maxy = (float) rect->y + rect->h;
+
+ vertices[0].x = minx;
+ vertices[0].y = miny;
+ vertices[0].z = 0.0f;
+ vertices[0].rhw = 1.0f;
+ vertices[0].color = color;
+ vertices[0].u = 0.0f;
+ vertices[0].v = 0.0f;
+
+ vertices[1].x = maxx;
+ vertices[1].y = miny;
+ vertices[1].z = 0.0f;
+ vertices[1].rhw = 1.0f;
+ vertices[1].color = color;
+ vertices[1].u = 0.0f;
+ vertices[1].v = 0.0f;
+
+ vertices[2].x = maxx;
+ vertices[2].y = maxy;
+ vertices[2].z = 0.0f;
+ vertices[2].rhw = 1.0f;
+ vertices[2].color = color;
+ vertices[2].u = 0.0f;
+ vertices[2].v = 0.0f;
+
+ vertices[3].x = minx;
+ vertices[3].y = maxy;
+ vertices[3].z = 0.0f;
+ vertices[3].rhw = 1.0f;
+ vertices[3].color = color;
+ vertices[3].u = 0.0f;
+ vertices[3].v = 0.0f;
+
+ result =
+ IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
+ 2, vertices, sizeof(*vertices));
+ if (FAILED(result)) {
+ D3D_SetError("DrawPrimitiveUP()", result);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_Rect * dstrect)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
+ LPDIRECT3DPIXELSHADER9 shader = NULL;
+ float minx, miny, maxx, maxy;
+ float minu, maxu, minv, maxv;
+ DWORD color;
+ Vertex vertices[4];
+ HRESULT result;
+
+ if (data->beginScene) {
+ IDirect3DDevice9_BeginScene(data->device);
+ data->beginScene = SDL_FALSE;
+ }
+
+ minx = (float) dstrect->x - 0.5f;
+ miny = (float) dstrect->y - 0.5f;
+ maxx = (float) dstrect->x + dstrect->w - 0.5f;
+ maxy = (float) dstrect->y + dstrect->h - 0.5f;
+
+ minu = (float) srcrect->x / texture->w;
+ maxu = (float) (srcrect->x + srcrect->w) / texture->w;
+ minv = (float) srcrect->y / texture->h;
+ maxv = (float) (srcrect->y + srcrect->h) / texture->h;
+
+ color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
+
+ vertices[0].x = minx;
+ vertices[0].y = miny;
+ vertices[0].z = 0.0f;
+ vertices[0].rhw = 1.0f;
+ vertices[0].color = color;
+ vertices[0].u = minu;
+ vertices[0].v = minv;
+
+ vertices[1].x = maxx;
+ vertices[1].y = miny;
+ vertices[1].z = 0.0f;
+ vertices[1].rhw = 1.0f;
+ vertices[1].color = color;
+ vertices[1].u = maxu;
+ vertices[1].v = minv;
+
+ vertices[2].x = maxx;
+ vertices[2].y = maxy;
+ vertices[2].z = 0.0f;
+ vertices[2].rhw = 1.0f;
+ vertices[2].color = color;
+ vertices[2].u = maxu;
+ vertices[2].v = maxv;
+
+ vertices[3].x = minx;
+ vertices[3].y = maxy;
+ vertices[3].z = 0.0f;
+ vertices[3].rhw = 1.0f;
+ vertices[3].color = color;
+ vertices[3].u = minu;
+ vertices[3].v = maxv;
+
+ D3D_SetBlendMode(data, texture->blendMode);
+
+ IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
+ D3DTEXF_LINEAR);
+ IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
+ D3DTEXF_LINEAR);
+
+ result =
+ IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
+ texturedata->texture);
+ if (FAILED(result)) {
+ D3D_SetError("SetTexture()", result);
+ return -1;
+ }
+ if (shader) {
+ result = IDirect3DDevice9_SetPixelShader(data->device, shader);
+ if (FAILED(result)) {
+ D3D_SetError("SetShader()", result);
+ return -1;
+ }
+ }
+ result =
+ IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
+ vertices, sizeof(*vertices));
+ if (FAILED(result)) {
+ D3D_SetError("DrawPrimitiveUP()", result);
+ return -1;
+ }
+ if (shader) {
+ result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
+ if (FAILED(result)) {
+ D3D_SetError("SetShader()", result);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+ Uint32 format, void * pixels, int pitch)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ D3DSURFACE_DESC desc;
+ LPDIRECT3DSURFACE9 backBuffer;
+ LPDIRECT3DSURFACE9 surface;
+ RECT d3drect;
+ D3DLOCKED_RECT locked;
+ HRESULT result;
+
+ result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
+ if (FAILED(result)) {
+ D3D_SetError("GetBackBuffer()", result);
+ return -1;
+ }
+
+ result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
+ if (FAILED(result)) {
+ D3D_SetError("GetDesc()", result);
+ IDirect3DSurface9_Release(backBuffer);
+ return -1;
+ }
+
+ result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
+ if (FAILED(result)) {
+ D3D_SetError("CreateOffscreenPlainSurface()", result);
+ IDirect3DSurface9_Release(backBuffer);
+ return -1;
+ }
+
+ result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
+ if (FAILED(result)) {
+ D3D_SetError("GetRenderTargetData()", result);
+ IDirect3DSurface9_Release(surface);
+ IDirect3DSurface9_Release(backBuffer);
+ return -1;
+ }
+
+ d3drect.left = rect->x;
+ d3drect.right = rect->x + rect->w;
+ d3drect.top = rect->y;
+ d3drect.bottom = rect->y + rect->h;
+
+ result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
+ if (FAILED(result)) {
+ D3D_SetError("LockRect()", result);
+ IDirect3DSurface9_Release(surface);
+ IDirect3DSurface9_Release(backBuffer);
+ return -1;
+ }
+
+ SDL_ConvertPixels(rect->w, rect->h,
+ D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
+ format, pixels, pitch);
+
+ IDirect3DSurface9_UnlockRect(surface);
+
+ IDirect3DSurface9_Release(surface);
+ IDirect3DSurface9_Release(backBuffer);
+
+ return 0;
+}
+
+static void
+D3D_RenderPresent(SDL_Renderer * renderer)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+ HRESULT result;
+
+ if (!data->beginScene) {
+ IDirect3DDevice9_EndScene(data->device);
+ data->beginScene = SDL_TRUE;
+ }
+
+ result = IDirect3DDevice9_TestCooperativeLevel(data->device);
+ if (result == D3DERR_DEVICELOST) {
+ /* We'll reset later */
+ return;
+ }
+ if (result == D3DERR_DEVICENOTRESET) {
+ D3D_Reset(renderer);
+ }
+ result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
+ if (FAILED(result)) {
+ D3D_SetError("Present()", result);
+ }
+}
+
+static void
+D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
+
+ if (!data) {
+ return;
+ }
+ if (data->texture) {
+ IDirect3DTexture9_Release(data->texture);
+ }
+ SDL_free(data);
+ texture->driverdata = NULL;
+}
+
+static void
+D3D_DestroyRenderer(SDL_Renderer * renderer)
+{
+ D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+
+ if (data) {
+ if (data->device) {
+ IDirect3DDevice9_Release(data->device);
+ }
+ if (data->d3d) {
+ IDirect3D9_Release(data->d3d);
+ SDL_UnloadObject(data->d3dDLL);
+ }
+ SDL_free(data);
+ }
+ SDL_free(renderer);
+}
+
+#endif /* SDL_VIDEO_RENDER_D3D */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/render/opengl/SDL_render_gl.c Sat Feb 05 12:01:11 2011 -0800
@@ -0,0 +1,826 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2010 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#if SDL_VIDEO_RENDER_OGL
+
+#include "SDL_opengl.h"
+#include "../SDL_sysrender.h"
+
+#ifdef __MACOSX__
+#include <OpenGL/OpenGL.h>
+#endif
+
+
+/* OpenGL renderer implementation */
+
+/* Details on optimizing the texture path on Mac OS X:
+ http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html
+*/
+
+/* Used to re-create the window with OpenGL capability */
+extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
+
+static const float inv255f = 1.0f / 255.0f;
+
+static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
+static void GL_WindowEvent(SDL_Renderer * renderer,
+ const SDL_WindowEvent *event);
+static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, const void *pixels,
+ int pitch);
+static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch);
+static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int GL_RenderClear(SDL_Renderer * renderer);
+static int GL_RenderDrawPoints(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int GL_RenderDrawLines(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int GL_RenderFillRects(SDL_Renderer * renderer,
+ const SDL_Rect ** rects, int count);
+static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+ Uint32 pixel_format, void * pixels, int pitch);
+static void GL_RenderPresent(SDL_Renderer * renderer);
+static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static void GL_DestroyRenderer(SDL_Renderer * renderer);
+
+
+SDL_RenderDriver GL_RenderDriver = {
+ GL_CreateRenderer,
+ {
+ "opengl",
+ (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
+ 1,
+ {SDL_PIXELFORMAT_ARGB8888},
+ 0,
+ 0}
+};
+
+typedef struct
+{
+ SDL_GLContext context;
+ SDL_bool updateSize;
+ SDL_bool GL_ARB_texture_rectangle_supported;
+ int blendMode;
+
+ /* OpenGL functions */
+#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
+#include "../../video/SDL_glfuncs.h"
+#undef SDL_PROC
+
+ void (*glTextureRangeAPPLE) (GLenum target, GLsizei length,
+ const GLvoid * pointer);
+} GL_RenderData;
+
+typedef struct
+{
+ GLuint texture;
+ GLenum type;
+ GLfloat texw;
+ GLfloat texh;
+ GLenum format;
+ GLenum formattype;
+ void *pixels;
+ int pitch;
+} GL_TextureData;
+
+
+static void
+GL_SetError(const char *prefix, GLenum result)
+{
+ const char *error;
+
+ switch (result) {
+ case GL_NO_ERROR:
+ error = "GL_NO_ERROR";
+ break;
+ case GL_INVALID_ENUM:
+ error = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ error = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ error = "GL_INVALID_OPERATION";
+ break;
+ case GL_STACK_OVERFLOW:
+ error = "GL_STACK_OVERFLOW";
+ break;
+ case GL_STACK_UNDERFLOW:
+ error = "GL_STACK_UNDERFLOW";
+ break;
+ case GL_OUT_OF_MEMORY:
+ error = "GL_OUT_OF_MEMORY";
+ break;
+ case GL_TABLE_TOO_LARGE:
+ error = "GL_TABLE_TOO_LARGE";
+ break;
+ default:
+ error = "UNKNOWN";
+ break;
+ }
+ SDL_SetError("%s: %s", prefix, error);
+}
+
+static int
+GL_LoadFunctions(GL_RenderData * data)
+{
+#ifdef __SDL_NOGETPROCADDR__
+#define SDL_PROC(ret,func,params) data->func=func;
+#else
+#define SDL_PROC(ret,func,params) \
+ do { \
+ data->func = SDL_GL_GetProcAddress(#func); \
+ if ( ! data->func ) { \
+ SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
+ return -1; \
+ } \
+ } while ( 0 );
+#endif /* __SDL_NOGETPROCADDR__ */
+
+#include "../../video/SDL_glfuncs.h"
+#undef SDL_PROC
+ return 0;
+}
+
+SDL_Renderer *
+GL_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+ SDL_Renderer *renderer;
+ GL_RenderData *data;
+ GLint value;
+ Uint32 window_flags;
+
+ window_flags = SDL_GetWindowFlags(window);
+ if (!(window_flags & SDL_WINDOW_OPENGL)) {
+ if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
+ return NULL;
+ }
+ }
+
+ renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+ if (!renderer) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ GL_DestroyRenderer(renderer);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ renderer->WindowEvent = GL_WindowEvent;
+ renderer->CreateTexture = GL_CreateTexture;
+ renderer->UpdateTexture = GL_UpdateTexture;
+ renderer->LockTexture = GL_LockTexture;
+ renderer->UnlockTexture = GL_UnlockTexture;
+ renderer->RenderClear = GL_RenderClear;
+ renderer->RenderDrawPoints = GL_RenderDrawPoints;
+ renderer->RenderDrawLines = GL_RenderDrawLines;
+ renderer->RenderFillRects = GL_RenderFillRects;
+ renderer->RenderCopy = GL_RenderCopy;
+ renderer->RenderReadPixels = GL_RenderReadPixels;
+ renderer->RenderPresent = GL_RenderPresent;
+ renderer->DestroyTexture = GL_DestroyTexture;
+ renderer->DestroyRenderer = GL_DestroyRenderer;
+ renderer->info = GL_RenderDriver.info;
+ renderer->driverdata = data;
+
+ renderer->info.flags = SDL_RENDERER_ACCELERATED;
+
+ if (GL_LoadFunctions(data) < 0) {
+ GL_DestroyRenderer(renderer);
+ return NULL;
+ }
+
+ data->context = SDL_GL_CreateContext(window);
+ if (!data->context) {
+ GL_DestroyRenderer(renderer);
+ return NULL;
+ }
+ if (SDL_GL_MakeCurrent(window, data->context) < 0) {
+ GL_DestroyRenderer(renderer);
+ return NULL;
+ }
+#ifdef __MACOSX__
+ /* Enable multi-threaded rendering */
+ /* Disabled until Ryan finishes his VBO/PBO code...
+ CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
+ */
+#endif
+
+ if (flags & SDL_RENDERER_PRESENTVSYNC) {
+ SDL_GL_SetSwapInterval(1);
+ } else {
+ SDL_GL_SetSwapInterval(0);
+ }
+ if (SDL_GL_GetSwapInterval() > 0) {
+ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+ }
+
+ data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+ renderer->info.max_texture_width = value;
+ data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+ renderer->info.max_texture_height = value;
+
+ if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
+ || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
+ data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
+ }
+ if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
+ data->glTextureRangeAPPLE =
+ (void (*)(GLenum, GLsizei, const GLvoid *))
+ SDL_GL_GetProcAddress("glTextureRangeAPPLE");
+ }
+
+ /* Set up parameters for rendering */
+ data->blendMode = -1;
+ data->glDisable(GL_DEPTH_TEST);
+ data->glDisable(GL_CULL_FACE);
+ /* This ended up causing video discrepancies between OpenGL and Direct3D */
+ /*data->glEnable(GL_LINE_SMOOTH);*/
+ if (data->GL_ARB_texture_rectangle_supported) {
+ data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ } else {
+ data->glEnable(GL_TEXTURE_2D);
+ }
+ data->updateSize = SDL_TRUE;
+
+ return renderer;
+}
+
+static SDL_GLContext SDL_CurrentContext = NULL;
+
+static int
+GL_ActivateRenderer(SDL_Renderer * renderer)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ SDL_Window *window = renderer->window;
+
+ if (SDL_CurrentContext != data->context) {
+ if (SDL_GL_MakeCurrent(window, data->context) < 0) {
+ return -1;
+ }
+ SDL_CurrentContext = data->context;
+ }
+ if (data->updateSize) {
+ int w, h;
+
+ SDL_GetWindowSize(window, &w, &h);
+ data->glMatrixMode(GL_PROJECTION);
+ data->glLoadIdentity();
+ data->glMatrixMode(GL_MODELVIEW);
+ data->glLoadIdentity();
+ data->glViewport(0, 0, w, h);
+ data->glOrtho(0.0, (GLdouble) w, (GLdouble) h, 0.0, 0.0, 1.0);
+ data->updateSize = SDL_FALSE;
+ }
+ return 0;
+}
+
+static void
+GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+
+ if (event->event == SDL_WINDOWEVENT_RESIZED) {
+ /* Rebind the context to the window area and update matrices */
+ SDL_CurrentContext = NULL;
+ data->updateSize = SDL_TRUE;
+ }
+}
+
+static __inline__ int
+power_of_2(int input)
+{
+ int value = 1;
+
+ while (value < input) {
+ value <<= 1;
+ }
+ return value;
+}
+
+static __inline__ SDL_bool
+convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
+ GLint* internalFormat, GLenum* format, GLenum* type)
+{
+ switch (pixel_format) {
+ case SDL_PIXELFORMAT_RGB888:
+ case SDL_PIXELFORMAT_ARGB8888:
+ *internalFormat = GL_RGBA8;
+ *format = GL_BGRA;
+ *type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ default:
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+}
+
+static int
+GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ GL_TextureData *data;
+ GLint internalFormat;
+ GLenum format, type;
+ int texture_w, texture_h;
+ GLenum result;
+
+ GL_ActivateRenderer(renderer);
+
+ if (!convert_format(renderdata, texture->format, &internalFormat,
+ &format, &type)) {
+ SDL_SetError("Texture format %s not supported by OpenGL",
+ SDL_GetPixelFormatName(texture->format));
+ return -1;
+ }
+
+ data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ SDL_OutOfMemory();
+ return -1;
+ }
+
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
+ data->pixels = SDL_malloc(texture->h * data->pitch);
+ if (!data->pixels) {
+ SDL_OutOfMemory();
+ SDL_free(data);
+ return -1;
+ }
+ }
+
+ texture->driverdata = data;
+
+ renderdata->glGetError();
+ renderdata->glGenTextures(1, &data->texture);
+ if (renderdata->GL_ARB_texture_rectangle_supported) {
+ data->type = GL_TEXTURE_RECTANGLE_ARB;
+ texture_w = texture->w;
+ texture_h = texture->h;
+ data->texw = (GLfloat) texture_w;
+ data->texh = (GLfloat) texture_h;
+ } else {
+ data->type = GL_TEXTURE_2D;
+ texture_w = power_of_2(texture->w);
+ texture_h = power_of_2(texture->h);
+ data->texw = (GLfloat) (texture->w) / texture_w;
+ data->texh = (GLfloat) texture->h / texture_h;
+ }
+
+ data->format = format;
+ data->formattype = type;
+ renderdata->glEnable(data->type);
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+#ifdef __MACOSX__
+#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#endif
+#ifndef STORAGE_CACHED_APPLE
+#define STORAGE_CACHED_APPLE 0x85BE
+#endif
+#ifndef STORAGE_SHARED_APPLE
+#define STORAGE_SHARED_APPLE 0x85BF
+#endif
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
+ GL_STORAGE_SHARED_APPLE);
+ } else {
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
+ GL_STORAGE_CACHED_APPLE);
+ }
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING
+ && texture->format == SDL_PIXELFORMAT_ARGB8888) {
+ renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+ renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
+ texture_h, 0, format, type, data->pixels);
+ }
+ else
+#endif
+ {
+ renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
+ texture_h, 0, format, type, NULL);
+ }
+ renderdata->glDisable(data->type);
+ result = renderdata->glGetError();
+ if (result != GL_NO_ERROR) {
+ GL_SetError("glTexImage2D()", result);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
+ int pitch)
+{
+ renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
+ (pitch / SDL_BYTESPERPIXEL(texture->format)));
+}
+
+static int
+GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, const void *pixels, int pitch)
+{
+ GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ GL_TextureData *data = (GL_TextureData *) texture->driverdata;
+ GLenum result;
+
+ GL_ActivateRenderer(renderer);
+
+ renderdata->glGetError();
+ SetupTextureUpdate(renderdata, texture, pitch);
+ renderdata->glEnable(data->type);
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
+ rect->h, data->format, data->formattype,
+ pixels);
+ renderdata->glDisable(data->type);
+ result = renderdata->glGetError();
+ if (result != GL_NO_ERROR) {
+ GL_SetError("glTexSubImage2D()", result);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch)
+{
+ GL_TextureData *data = (GL_TextureData *) texture->driverdata;
+
+ *pixels =
+ (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
+ rect->x * SDL_BYTESPERPIXEL(texture->format));
+ *pitch = data->pitch;
+ return 0;
+}
+
+static void
+GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ GL_TextureData *data = (GL_TextureData *) texture->driverdata;
+
+ GL_ActivateRenderer(renderer);
+
+ SetupTextureUpdate(renderdata, texture, data->pitch);
+ renderdata->glEnable(data->type);
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glTexSubImage2D(data->type, 0, 0, 0, texture->w, texture->h,
+ data->format, data->formattype, data->pixels);
+ renderdata->glDisable(data->type);
+}
+
+static void
+GL_SetBlendMode(GL_RenderData * data, int blendMode)
+{
+ if (blendMode != data->blendMode) {
+ switch (blendMode) {
+ case SDL_BLENDMODE_NONE:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ data->glDisable(GL_BLEND);
+ break;
+ case SDL_BLENDMODE_BLEND:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ data->glEnable(GL_BLEND);
+ data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case SDL_BLENDMODE_ADD:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ data->glEnable(GL_BLEND);
+ data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ break;
+ case SDL_BLENDMODE_MOD:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ data->glEnable(GL_BLEND);
+ data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+ break;
+ }
+ data->blendMode = blendMode;
+ }
+}
+
+static int
+GL_RenderClear(SDL_Renderer * renderer)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+
+ GL_ActivateRenderer(renderer);
+
+ data->glClearColor((GLfloat) renderer->r * inv255f,
+ (GLfloat) renderer->g * inv255f,
+ (GLfloat) renderer->b * inv255f,
+ (GLfloat) renderer->a * inv255f);
+
+ data->glClear(GL_COLOR_BUFFER_BIT);
+
+ return 0;
+}
+
+static int
+GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ int i;
+
+ GL_ActivateRenderer(renderer);
+
+ GL_SetBlendMode(data, renderer->blendMode);
+
+ data->glColor4f((GLfloat) renderer->r * inv255f,
+ (GLfloat) renderer->g * inv255f,
+ (GLfloat) renderer->b * inv255f,
+ (GLfloat) renderer->a * inv255f);
+
+ data->glBegin(GL_POINTS);
+ for (i = 0; i < count; ++i) {
+ data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
+ }
+ data->glEnd();
+
+ return 0;
+}
+
+static int
+GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ int i;
+
+ GL_ActivateRenderer(renderer);
+
+ GL_SetBlendMode(data, renderer->blendMode);
+
+ data->glColor4f((GLfloat) renderer->r * inv255f,
+ (GLfloat) renderer->g * inv255f,
+ (GLfloat) renderer->b * inv255f,
+ (GLfloat) renderer->a * inv255f);
+
+ if (count > 2 &&
+ points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
+ data->glBegin(GL_LINE_LOOP);
+ /* GL_LINE_LOOP takes care of the final segment */
+ --count;
+ for (i = 0; i < count; ++i) {
+ data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
+ }
+ data->glEnd();
+ } else {
+#if defined(__APPLE__) || defined(__WIN32__)
+#else
+ int x1, y1, x2, y2;
+#endif
+
+ data->glBegin(GL_LINE_STRIP);
+ for (i = 0; i < count; ++i) {
+ data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
+ }
+ data->glEnd();
+
+ /* The line is half open, so we need one more point to complete it.
+ * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
+ * If we have to, we can use vertical line and horizontal line textures
+ * for vertical and horizontal lines, and then create custom textures
+ * for diagonal lines and software render those. It's terrible, but at
+ * least it would be pixel perfect.
+ */
+ data->glBegin(GL_POINTS);
+#if defined(__APPLE__) || defined(__WIN32__)
+ /* Mac OS X and Windows seem to always leave the second point open */
+ data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
+#else
+ /* Linux seems to leave the right-most or bottom-most point open */
+ x1 = points[0].x;
+ y1 = points[0].y;
+ x2 = points[count-1].x;
+ y2 = points[count-1].y;
+
+ if (x1 > x2) {
+ data->glVertex2f(0.5f + x1, 0.5f + y1);
+ } else if (x2 > x1) {
+ data->glVertex2f(0.5f + x2, 0.5f + y2);
+ } else if (y1 > y2) {
+ data->glVertex2f(0.5f + x1, 0.5f + y1);
+ } else if (y2 > y1) {
+ data->glVertex2f(0.5f + x2, 0.5f + y2);
+ }
+#endif
+ data->glEnd();
+ }
+
+ return 0;
+}
+
+static int
+GL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ int i;
+
+ GL_ActivateRenderer(renderer);
+
+ GL_SetBlendMode(data, renderer->blendMode);
+
+ data->glColor4f((GLfloat) renderer->r * inv255f,
+ (GLfloat) renderer->g * inv255f,
+ (GLfloat) renderer->b * inv255f,
+ (GLfloat) renderer->a * inv255f);
+
+ for (i = 0; i < count; ++i) {
+ const SDL_Rect *rect = rects[i];
+
+ data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
+ }
+
+ return 0;
+}
+
+static int
+GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_Rect * dstrect)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
+ int minx, miny, maxx, maxy;
+ GLfloat minu, maxu, minv, maxv;
+
+ GL_ActivateRenderer(renderer);
+
+ minx = dstrect->x;
+ miny = dstrect->y;
+ maxx = dstrect->x + dstrect->w;
+ maxy = dstrect->y + dstrect->h;
+
+ minu = (GLfloat) srcrect->x / texture->w;
+ minu *= texturedata->texw;
+ maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
+ maxu *= texturedata->texw;
+ minv = (GLfloat) srcrect->y / texture->h;
+ minv *= texturedata->texh;
+ maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
+ maxv *= texturedata->texh;
+
+ data->glEnable(texturedata->type);
+ data->glBindTexture(texturedata->type, texturedata->texture);
+
+ if (texture->modMode) {
+ data->glColor4f((GLfloat) texture->r * inv255f,
+ (GLfloat) texture->g * inv255f,
+ (GLfloat) texture->b * inv255f,
+ (GLfloat) texture->a * inv255f);
+ } else {
+ data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ GL_SetBlendMode(data, texture->blendMode);
+
+ data->glBegin(GL_TRIANGLE_STRIP);
+ data->glTexCoord2f(minu, minv);
+ data->glVertex2f((GLfloat) minx, (GLfloat) miny);
+ data->glTexCoord2f(maxu, minv);
+ data->glVertex2f((GLfloat) maxx, (GLfloat) miny);
+ data->glTexCoord2f(minu, maxv);
+ data->glVertex2f((GLfloat) minx, (GLfloat) maxy);
+ data->glTexCoord2f(maxu, maxv);
+ data->glVertex2f((GLfloat) maxx, (GLfloat) maxy);
+ data->glEnd();
+
+ data->glDisable(texturedata->type);
+
+ return 0;
+}
+
+static int
+GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+ Uint32 pixel_format, void * pixels, int pitch)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ SDL_Window *window = renderer->window;
+ GLint internalFormat;
+ GLenum format, type;
+ Uint8 *src, *dst, *tmp;
+ int w, h, length, rows;
+
+ GL_ActivateRenderer(renderer);
+
+ if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) {
+ /* FIXME: Do a temp copy to a format that is supported */
+ SDL_SetError("Unsupported pixel format");
+ return -1;
+ }
+
+ SDL_GetWindowSize(window, &w, &h);
+
+ data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ data->glPixelStorei(GL_PACK_ROW_LENGTH,
+ (pitch / SDL_BYTESPERPIXEL(pixel_format)));
+
+ data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
+ format, type, pixels);
+
+ /* Flip the rows to be top-down */
+ length = rect->w * SDL_BYTESPERPIXEL(pixel_format);
+ src = (Uint8*)pixels + (rect->h-1)*pitch;
+ dst = (Uint8*)pixels;
+ tmp = SDL_stack_alloc(Uint8, length);
+ rows = rect->h / 2;
+ while (rows--) {
+ SDL_memcpy(tmp, dst, length);
+ SDL_memcpy(dst, src, length);
+ SDL_memcpy(src, tmp, length);
+ dst += pitch;
+ src -= pitch;
+ }
+ SDL_stack_free(tmp);
+
+ return 0;
+}
+
+static void
+GL_RenderPresent(SDL_Renderer * renderer)
+{
+ GL_ActivateRenderer(renderer);
+
+ SDL_GL_SwapWindow(renderer->window);
+}
+
+static void
+GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
+ GL_TextureData *data = (GL_TextureData *) texture->driverdata;
+
+ GL_ActivateRenderer(renderer);
+
+ if (!data) {
+ return;
+ }
+ if (data->texture) {
+ renderdata->glDeleteTextures(1, &data->texture);
+ }
+ if (data->pixels) {
+ SDL_free(data->pixels);
+ }
+ SDL_free(data);
+ texture->driverdata = NULL;
+}
+
+static void
+GL_DestroyRenderer(SDL_Renderer * renderer)
+{
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+
+ if (data) {
+ if (data->context) {
+ /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
+ SDL_GL_DeleteContext(data->context);
+ }
+ SDL_free(data);
+ }
+ SDL_free(renderer);
+}
+
+#endif /* SDL_VIDEO_RENDER_OGL */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/render/opengl/SDL_renderer_gl.c Sat Feb 05 11:54:46 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,826 +0,0 @@
-/*
- SDL - Simple DirectMedia Layer
- Copyright (C) 1997-2010 Sam Lantinga
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- Sam Lantinga
- slouken@libsdl.org
-*/
-#include "SDL_config.h"
-
-#if SDL_VIDEO_RENDER_OGL
-
-#include "SDL_opengl.h"
-#include "../SDL_sysrender.h"
-
-#ifdef __MACOSX__
-#include <OpenGL/OpenGL.h>
-#endif
-
-
-/* OpenGL renderer implementation */
-
-/* Details on optimizing the texture path on Mac OS X:
- http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html
-*/
-
-/* Used to re-create the window with OpenGL capability */
-extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
-
-static const float inv255f = 1.0f / 255.0f;
-
-static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
-static void GL_WindowEvent(SDL_Renderer * renderer,
- const SDL_WindowEvent *event);
-static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, const void *pixels,
- int pitch);
-static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch);
-static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int GL_RenderClear(SDL_Renderer * renderer);
-static int GL_RenderDrawPoints(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int GL_RenderDrawLines(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int GL_RenderFillRects(SDL_Renderer * renderer,
- const SDL_Rect ** rects, int count);
-static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_Rect * dstrect);
-static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
- Uint32 pixel_format, void * pixels, int pitch);
-static void GL_RenderPresent(SDL_Renderer * renderer);
-static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static void GL_DestroyRenderer(SDL_Renderer * renderer);
-
-
-SDL_RenderDriver GL_RenderDriver = {
- GL_CreateRenderer,
- {
- "opengl",
- (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
- 1,
- {SDL_PIXELFORMAT_ARGB8888},
- 0,
- 0}
-};
-
-typedef struct
-{
- SDL_GLContext context;
- SDL_bool updateSize;
- SDL_bool GL_ARB_texture_rectangle_supported;
- int blendMode;
-
- /* OpenGL functions */
-#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
-#include "../../video/SDL_glfuncs.h"
-#undef SDL_PROC
-
- void (*glTextureRangeAPPLE) (GLenum target, GLsizei length,
- const GLvoid * pointer);
-} GL_RenderData;
-
-typedef struct
-{
- GLuint texture;
- GLenum type;
- GLfloat texw;
- GLfloat texh;
- GLenum format;
- GLenum formattype;
- void *pixels;
- int pitch;
-} GL_TextureData;
-
-
-static void
-GL_SetError(const char *prefix, GLenum result)
-{
- const char *error;
-
- switch (result) {
- case GL_NO_ERROR:
- error = "GL_NO_ERROR";
- break;
- case GL_INVALID_ENUM:
- error = "GL_INVALID_ENUM";
- break;
- case GL_INVALID_VALUE:
- error = "GL_INVALID_VALUE";
- break;
- case GL_INVALID_OPERATION:
- error = "GL_INVALID_OPERATION";
- break;
- case GL_STACK_OVERFLOW:
- error = "GL_STACK_OVERFLOW";
- break;
- case GL_STACK_UNDERFLOW:
- error = "GL_STACK_UNDERFLOW";
- break;
- case GL_OUT_OF_MEMORY:
- error = "GL_OUT_OF_MEMORY";
- break;
- case GL_TABLE_TOO_LARGE:
- error = "GL_TABLE_TOO_LARGE";
- break;
- default:
- error = "UNKNOWN";
- break;
- }
- SDL_SetError("%s: %s", prefix, error);
-}
-
-static int
-GL_LoadFunctions(GL_RenderData * data)
-{
-#ifdef __SDL_NOGETPROCADDR__
-#define SDL_PROC(ret,func,params) data->func=func;
-#else
-#define SDL_PROC(ret,func,params) \
- do { \
- data->func = SDL_GL_GetProcAddress(#func); \
- if ( ! data->func ) { \
- SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
- return -1; \
- } \
- } while ( 0 );
-#endif /* __SDL_NOGETPROCADDR__ */
-
-#include "../../video/SDL_glfuncs.h"
-#undef SDL_PROC
- return 0;
-}
-
-SDL_Renderer *
-GL_CreateRenderer(SDL_Window * window, Uint32 flags)
-{
- SDL_Renderer *renderer;
- GL_RenderData *data;
- GLint value;
- Uint32 window_flags;
-
- window_flags = SDL_GetWindowFlags(window);
- if (!(window_flags & SDL_WINDOW_OPENGL)) {
- if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
- return NULL;
- }
- }
-
- renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
- if (!renderer) {
- SDL_OutOfMemory();
- return NULL;
- }
-
- data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- GL_DestroyRenderer(renderer);
- SDL_OutOfMemory();
- return NULL;
- }
-
- renderer->WindowEvent = GL_WindowEvent;
- renderer->CreateTexture = GL_CreateTexture;
- renderer->UpdateTexture = GL_UpdateTexture;
- renderer->LockTexture = GL_LockTexture;
- renderer->UnlockTexture = GL_UnlockTexture;
- renderer->RenderClear = GL_RenderClear;
- renderer->RenderDrawPoints = GL_RenderDrawPoints;
- renderer->RenderDrawLines = GL_RenderDrawLines;
- renderer->RenderFillRects = GL_RenderFillRects;
- renderer->RenderCopy = GL_RenderCopy;
- renderer->RenderReadPixels = GL_RenderReadPixels;
- renderer->RenderPresent = GL_RenderPresent;
- renderer->DestroyTexture = GL_DestroyTexture;
- renderer->DestroyRenderer = GL_DestroyRenderer;
- renderer->info = GL_RenderDriver.info;
- renderer->driverdata = data;
-
- renderer->info.flags = SDL_RENDERER_ACCELERATED;
-
- if (GL_LoadFunctions(data) < 0) {
- GL_DestroyRenderer(renderer);
- return NULL;
- }
-
- data->context = SDL_GL_CreateContext(window);
- if (!data->context) {
- GL_DestroyRenderer(renderer);
- return NULL;
- }
- if (SDL_GL_MakeCurrent(window, data->context) < 0) {
- GL_DestroyRenderer(renderer);
- return NULL;
- }
-#ifdef __MACOSX__
- /* Enable multi-threaded rendering */
- /* Disabled until Ryan finishes his VBO/PBO code...
- CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
- */
-#endif
-
- if (flags & SDL_RENDERER_PRESENTVSYNC) {
- SDL_GL_SetSwapInterval(1);
- } else {
- SDL_GL_SetSwapInterval(0);
- }
- if (SDL_GL_GetSwapInterval() > 0) {
- renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
- }
-
- data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
- renderer->info.max_texture_width = value;
- data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
- renderer->info.max_texture_height = value;
-
- if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
- || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
- data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
- }
- if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
- data->glTextureRangeAPPLE =
- (void (*)(GLenum, GLsizei, const GLvoid *))
- SDL_GL_GetProcAddress("glTextureRangeAPPLE");
- }
-
- /* Set up parameters for rendering */
- data->blendMode = -1;
- data->glDisable(GL_DEPTH_TEST);
- data->glDisable(GL_CULL_FACE);
- /* This ended up causing video discrepancies between OpenGL and Direct3D */
- /*data->glEnable(GL_LINE_SMOOTH);*/
- if (data->GL_ARB_texture_rectangle_supported) {
- data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
- } else {
- data->glEnable(GL_TEXTURE_2D);
- }
- data->updateSize = SDL_TRUE;
-
- return renderer;
-}
-
-static SDL_GLContext SDL_CurrentContext = NULL;
-
-static int
-GL_ActivateRenderer(SDL_Renderer * renderer)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
- SDL_Window *window = renderer->window;
-
- if (SDL_CurrentContext != data->context) {
- if (SDL_GL_MakeCurrent(window, data->context) < 0) {
- return -1;
- }
- SDL_CurrentContext = data->context;
- }
- if (data->updateSize) {
- int w, h;
-
- SDL_GetWindowSize(window, &w, &h);
- data->glMatrixMode(GL_PROJECTION);
- data->glLoadIdentity();
- data->glMatrixMode(GL_MODELVIEW);
- data->glLoadIdentity();
- data->glViewport(0, 0, w, h);
- data->glOrtho(0.0, (GLdouble) w, (GLdouble) h, 0.0, 0.0, 1.0);
- data->updateSize = SDL_FALSE;
- }
- return 0;
-}
-
-static void
-GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
-
- if (event->event == SDL_WINDOWEVENT_RESIZED) {
- /* Rebind the context to the window area and update matrices */
- SDL_CurrentContext = NULL;
- data->updateSize = SDL_TRUE;
- }
-}
-
-static __inline__ int
-power_of_2(int input)
-{
- int value = 1;
-
- while (value < input) {
- value <<= 1;
- }
- return value;
-}
-
-static __inline__ SDL_bool
-convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
- GLint* internalFormat, GLenum* format, GLenum* type)
-{
- switch (pixel_format) {
- case SDL_PIXELFORMAT_RGB888:
- case SDL_PIXELFORMAT_ARGB8888:
- *internalFormat = GL_RGBA8;
- *format = GL_BGRA;
- *type = GL_UNSIGNED_INT_8_8_8_8_REV;
- break;
- default:
- return SDL_FALSE;
- }
- return SDL_TRUE;
-}
-
-static int
-GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
- GL_TextureData *data;
- GLint internalFormat;
- GLenum format, type;
- int texture_w, texture_h;
- GLenum result;
-
- GL_ActivateRenderer(renderer);
-
- if (!convert_format(renderdata, texture->format, &internalFormat,
- &format, &type)) {
- SDL_SetError("Texture format %s not supported by OpenGL",
- SDL_GetPixelFormatName(texture->format));
- return -1;
- }
-
- data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- SDL_OutOfMemory();
- return -1;
- }
-
- if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
- data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
- data->pixels = SDL_malloc(texture->h * data->pitch);
- if (!data->pixels) {
- SDL_OutOfMemory();
- SDL_free(data);
- return -1;
- }
- }
-
- texture->driverdata = data;
-
- renderdata->glGetError();
- renderdata->glGenTextures(1, &data->texture);
- if (renderdata->GL_ARB_texture_rectangle_supported) {
- data->type = GL_TEXTURE_RECTANGLE_ARB;
- texture_w = texture->w;
- texture_h = texture->h;
- data->texw = (GLfloat) texture_w;
- data->texh = (GLfloat) texture_h;
- } else {
- data->type = GL_TEXTURE_2D;
- texture_w = power_of_2(texture->w);
- texture_h = power_of_2(texture->h);
- data->texw = (GLfloat) (texture->w) / texture_w;
- data->texh = (GLfloat) texture->h / texture_h;
- }
-
- data->format = format;
- data->formattype = type;
- renderdata->glEnable(data->type);
- renderdata->glBindTexture(data->type, data->texture);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
- GL_LINEAR);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_EDGE);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_EDGE);
-#ifdef __MACOSX__
-#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
-#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
-#endif
-#ifndef STORAGE_CACHED_APPLE
-#define STORAGE_CACHED_APPLE 0x85BE
-#endif
-#ifndef STORAGE_SHARED_APPLE
-#define STORAGE_SHARED_APPLE 0x85BF
-#endif
- if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
- renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
- GL_STORAGE_SHARED_APPLE);
- } else {
- renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
- GL_STORAGE_CACHED_APPLE);
- }
- if (texture->access == SDL_TEXTUREACCESS_STREAMING
- && texture->format == SDL_PIXELFORMAT_ARGB8888) {
- renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
- renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
- texture_h, 0, format, type, data->pixels);
- }
- else
-#endif
- {
- renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
- texture_h, 0, format, type, NULL);
- }
- renderdata->glDisable(data->type);
- result = renderdata->glGetError();
- if (result != GL_NO_ERROR) {
- GL_SetError("glTexImage2D()", result);
- return -1;
- }
- return 0;
-}
-
-static void
-SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
- int pitch)
-{
- renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
- (pitch / SDL_BYTESPERPIXEL(texture->format)));
-}
-
-static int
-GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, const void *pixels, int pitch)
-{
- GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
- GL_TextureData *data = (GL_TextureData *) texture->driverdata;
- GLenum result;
-
- GL_ActivateRenderer(renderer);
-
- renderdata->glGetError();
- SetupTextureUpdate(renderdata, texture, pitch);
- renderdata->glEnable(data->type);
- renderdata->glBindTexture(data->type, data->texture);
- renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
- rect->h, data->format, data->formattype,
- pixels);
- renderdata->glDisable(data->type);
- result = renderdata->glGetError();
- if (result != GL_NO_ERROR) {
- GL_SetError("glTexSubImage2D()", result);
- return -1;
- }
- return 0;
-}
-
-static int
-GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch)
-{
- GL_TextureData *data = (GL_TextureData *) texture->driverdata;
-
- *pixels =
- (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
- rect->x * SDL_BYTESPERPIXEL(texture->format));
- *pitch = data->pitch;
- return 0;
-}
-
-static void
-GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
- GL_TextureData *data = (GL_TextureData *) texture->driverdata;
-
- GL_ActivateRenderer(renderer);
-
- SetupTextureUpdate(renderdata, texture, data->pitch);
- renderdata->glEnable(data->type);
- renderdata->glBindTexture(data->type, data->texture);
- renderdata->glTexSubImage2D(data->type, 0, 0, 0, texture->w, texture->h,
- data->format, data->formattype, data->pixels);
- renderdata->glDisable(data->type);
-}
-
-static void
-GL_SetBlendMode(GL_RenderData * data, int blendMode)
-{
- if (blendMode != data->blendMode) {
- switch (blendMode) {
- case SDL_BLENDMODE_NONE:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- data->glDisable(GL_BLEND);
- break;
- case SDL_BLENDMODE_BLEND:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- data->glEnable(GL_BLEND);
- data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- break;
- case SDL_BLENDMODE_ADD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- data->glEnable(GL_BLEND);
- data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- break;
- case SDL_BLENDMODE_MOD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- data->glEnable(GL_BLEND);
- data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
- break;
- }
- data->blendMode = blendMode;
- }
-}
-
-static int
-GL_RenderClear(SDL_Renderer * renderer)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
-
- GL_ActivateRenderer(renderer);
-
- data->glClearColor((GLfloat) renderer->r * inv255f,
- (GLfloat) renderer->g * inv255f,
- (GLfloat) renderer->b * inv255f,
- (GLfloat) renderer->a * inv255f);
-
- data->glClear(GL_COLOR_BUFFER_BIT);
-
- return 0;
-}
-
-static int
-GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
- int i;
-
- GL_ActivateRenderer(renderer);
-
- GL_SetBlendMode(data, renderer->blendMode);
-
- data->glColor4f((GLfloat) renderer->r * inv255f,
- (GLfloat) renderer->g * inv255f,
- (GLfloat) renderer->b * inv255f,
- (GLfloat) renderer->a * inv255f);
-
- data->glBegin(GL_POINTS);
- for (i = 0; i < count; ++i) {
- data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
- }
- data->glEnd();
-
- return 0;
-}
-
-static int
-GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
- int i;
-
- GL_ActivateRenderer(renderer);
-
- GL_SetBlendMode(data, renderer->blendMode);
-
- data->glColor4f((GLfloat) renderer->r * inv255f,
- (GLfloat) renderer->g * inv255f,
- (GLfloat) renderer->b * inv255f,
- (GLfloat) renderer->a * inv255f);
-
- if (count > 2 &&
- points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
- data->glBegin(GL_LINE_LOOP);
- /* GL_LINE_LOOP takes care of the final segment */
- --count;
- for (i = 0; i < count; ++i) {
- data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
- }
- data->glEnd();
- } else {
-#if defined(__APPLE__) || defined(__WIN32__)
-#else
- int x1, y1, x2, y2;
-#endif
-
- data->glBegin(GL_LINE_STRIP);
- for (i = 0; i < count; ++i) {
- data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
- }
- data->glEnd();
-
- /* The line is half open, so we need one more point to complete it.
- * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
- * If we have to, we can use vertical line and horizontal line textures
- * for vertical and horizontal lines, and then create custom textures
- * for diagonal lines and software render those. It's terrible, but at
- * least it would be pixel perfect.
- */
- data->glBegin(GL_POINTS);
-#if defined(__APPLE__) || defined(__WIN32__)
- /* Mac OS X and Windows seem to always leave the second point open */
- data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
-#else
- /* Linux seems to leave the right-most or bottom-most point open */
- x1 = points[0].x;
- y1 = points[0].y;
- x2 = points[count-1].x;
- y2 = points[count-1].y;
-
- if (x1 > x2) {
- data->glVertex2f(0.5f + x1, 0.5f + y1);
- } else if (x2 > x1) {
- data->glVertex2f(0.5f + x2, 0.5f + y2);
- } else if (y1 > y2) {
- data->glVertex2f(0.5f + x1, 0.5f + y1);
- } else if (y2 > y1) {
- data->glVertex2f(0.5f + x2, 0.5f + y2);
- }
-#endif
- data->glEnd();
- }
-
- return 0;
-}
-
-static int
-GL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
- int i;
-
- GL_ActivateRenderer(renderer);
-
- GL_SetBlendMode(data, renderer->blendMode);
-
- data->glColor4f((GLfloat) renderer->r * inv255f,
- (GLfloat) renderer->g * inv255f,
- (GLfloat) renderer->b * inv255f,
- (GLfloat) renderer->a * inv255f);
-
- for (i = 0; i < count; ++i) {
- const SDL_Rect *rect = rects[i];
-
- data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
- }
-
- return 0;
-}
-
-static int
-GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_Rect * dstrect)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
- GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
- int minx, miny, maxx, maxy;
- GLfloat minu, maxu, minv, maxv;
-
- GL_ActivateRenderer(renderer);
-
- minx = dstrect->x;
- miny = dstrect->y;
- maxx = dstrect->x + dstrect->w;
- maxy = dstrect->y + dstrect->h;
-
- minu = (GLfloat) srcrect->x / texture->w;
- minu *= texturedata->texw;
- maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
- maxu *= texturedata->texw;
- minv = (GLfloat) srcrect->y / texture->h;
- minv *= texturedata->texh;
- maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
- maxv *= texturedata->texh;
-
- data->glEnable(texturedata->type);
- data->glBindTexture(texturedata->type, texturedata->texture);
-
- if (texture->modMode) {
- data->glColor4f((GLfloat) texture->r * inv255f,
- (GLfloat) texture->g * inv255f,
- (GLfloat) texture->b * inv255f,
- (GLfloat) texture->a * inv255f);
- } else {
- data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- }
-
- GL_SetBlendMode(data, texture->blendMode);
-
- data->glBegin(GL_TRIANGLE_STRIP);
- data->glTexCoord2f(minu, minv);
- data->glVertex2f((GLfloat) minx, (GLfloat) miny);
- data->glTexCoord2f(maxu, minv);
- data->glVertex2f((GLfloat) maxx, (GLfloat) miny);
- data->glTexCoord2f(minu, maxv);
- data->glVertex2f((GLfloat) minx, (GLfloat) maxy);
- data->glTexCoord2f(maxu, maxv);
- data->glVertex2f((GLfloat) maxx, (GLfloat) maxy);
- data->glEnd();
-
- data->glDisable(texturedata->type);
-
- return 0;
-}
-
-static int
-GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
- Uint32 pixel_format, void * pixels, int pitch)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
- SDL_Window *window = renderer->window;
- GLint internalFormat;
- GLenum format, type;
- Uint8 *src, *dst, *tmp;
- int w, h, length, rows;
-
- GL_ActivateRenderer(renderer);
-
- if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) {
- /* FIXME: Do a temp copy to a format that is supported */
- SDL_SetError("Unsupported pixel format");
- return -1;
- }
-
- SDL_GetWindowSize(window, &w, &h);
-
- data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
- data->glPixelStorei(GL_PACK_ROW_LENGTH,
- (pitch / SDL_BYTESPERPIXEL(pixel_format)));
-
- data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
- format, type, pixels);
-
- /* Flip the rows to be top-down */
- length = rect->w * SDL_BYTESPERPIXEL(pixel_format);
- src = (Uint8*)pixels + (rect->h-1)*pitch;
- dst = (Uint8*)pixels;
- tmp = SDL_stack_alloc(Uint8, length);
- rows = rect->h / 2;
- while (rows--) {
- SDL_memcpy(tmp, dst, length);
- SDL_memcpy(dst, src, length);
- SDL_memcpy(src, tmp, length);
- dst += pitch;
- src -= pitch;
- }
- SDL_stack_free(tmp);
-
- return 0;
-}
-
-static void
-GL_RenderPresent(SDL_Renderer * renderer)
-{
- GL_ActivateRenderer(renderer);
-
- SDL_GL_SwapWindow(renderer->window);
-}
-
-static void
-GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
- GL_TextureData *data = (GL_TextureData *) texture->driverdata;
-
- GL_ActivateRenderer(renderer);
-
- if (!data) {
- return;
- }
- if (data->texture) {
- renderdata->glDeleteTextures(1, &data->texture);
- }
- if (data->pixels) {
- SDL_free(data->pixels);
- }
- SDL_free(data);
- texture->driverdata = NULL;
-}
-
-static void
-GL_DestroyRenderer(SDL_Renderer * renderer)
-{
- GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
-
- if (data) {
- if (data->context) {
- /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
- SDL_GL_DeleteContext(data->context);
- }
- SDL_free(data);
- }
- SDL_free(renderer);
-}
-
-#endif /* SDL_VIDEO_RENDER_OGL */
-
-/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/render/opengles/SDL_render_gles.c Sat Feb 05 12:01:11 2011 -0800
@@ -0,0 +1,748 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2010 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#if SDL_VIDEO_RENDER_OGL_ES
+
+#include "SDL_opengles.h"
+#include "../SDL_sysrender.h"
+
+#if defined(SDL_VIDEO_DRIVER_PANDORA)
+
+/* Empty function stub to get OpenGL ES 1.x support without */
+/* OpenGL ES extension GL_OES_draw_texture supported */
+GL_API void GL_APIENTRY
+glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height)
+{
+ return;
+}
+
+#endif /* PANDORA */
+
+/* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */
+
+/* Used to re-create the window with OpenGL capability */
+extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
+
+static const float inv255f = 1.0f / 255.0f;
+
+static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
+static void GLES_WindowEvent(SDL_Renderer * renderer,
+ const SDL_WindowEvent *event);
+static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, const void *pixels,
+ int pitch);
+static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch);
+static void GLES_UnlockTexture(SDL_Renderer * renderer,
+ SDL_Texture * texture);
+static int GLES_RenderDrawPoints(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int GLES_RenderDrawLines(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int GLES_RenderFillRects(SDL_Renderer * renderer,
+ const SDL_Rect ** rects, int count);
+static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_Rect * dstrect);
+static void GLES_RenderPresent(SDL_Renderer * renderer);
+static void GLES_DestroyTexture(SDL_Renderer * renderer,
+ SDL_Texture * texture);
+static void GLES_DestroyRenderer(SDL_Renderer * renderer);
+
+
+SDL_RenderDriver GL_ES_RenderDriver = {
+ GLES_CreateRenderer,
+ {
+ "opengl_es",
+ (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
+ 1,
+ {SDL_PIXELFORMAT_ABGR8888},
+ 0,
+ 0}
+};
+
+typedef struct
+{
+ SDL_GLContext context;
+ SDL_bool updateSize;
+ int blendMode;
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+
+ SDL_bool useDrawTexture;
+ SDL_bool GL_OES_draw_texture_supported;
+
+ /* OpenGL ES functions */
+#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
+#include "../../video/SDL_glesfuncs.h"
+#undef SDL_PROC
+
+} GLES_RenderData;
+
+typedef struct
+{
+ GLuint texture;
+ GLenum type;
+ GLfloat texw;
+ GLfloat texh;
+ GLenum format;
+ GLenum formattype;
+ void *pixels;
+ int pitch;
+} GLES_TextureData;
+
+static void
+GLES_SetError(const char *prefix, GLenum result)
+{
+ const char *error;
+
+ switch (result) {
+ case GL_NO_ERROR:
+ error = "GL_NO_ERROR";
+ break;
+ case GL_INVALID_ENUM:
+ error = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ error = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ error = "GL_INVALID_OPERATION";
+ break;
+ case GL_STACK_OVERFLOW:
+ error = "GL_STACK_OVERFLOW";
+ break;
+ case GL_STACK_UNDERFLOW:
+ error = "GL_STACK_UNDERFLOW";
+ break;
+ case GL_OUT_OF_MEMORY:
+ error = "GL_OUT_OF_MEMORY";
+ break;
+ default:
+ error = "UNKNOWN";
+ break;
+ }
+ SDL_SetError("%s: %s", prefix, error);
+}
+
+static int
+GLES_LoadFunctions(GLES_RenderData * data)
+{
+
+#define SDL_PROC(ret,func,params) \
+ data->func = func;
+#include "../../video/SDL_glesfuncs.h"
+#undef SDL_PROC
+
+ return 0;
+}
+
+SDL_Renderer *
+GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+
+ SDL_Renderer *renderer;
+ GLES_RenderData *data;
+ GLint value;
+ Uint32 window_flags;
+
+ window_flags = SDL_GetWindowFlags(window);
+ if (!(window_flags & SDL_WINDOW_OPENGL)) {
+ if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
+ return NULL;
+ }
+ }
+
+ renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+ if (!renderer) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ GLES_DestroyRenderer(renderer);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ renderer->WindowEvent = GLES_WindowEvent;
+ renderer->CreateTexture = GLES_CreateTexture;
+ renderer->UpdateTexture = GLES_UpdateTexture;
+ renderer->LockTexture = GLES_LockTexture;
+ renderer->UnlockTexture = GLES_UnlockTexture;
+ renderer->RenderDrawPoints = GLES_RenderDrawPoints;
+ renderer->RenderDrawLines = GLES_RenderDrawLines;
+ renderer->RenderFillRects = GLES_RenderFillRects;
+ renderer->RenderCopy = GLES_RenderCopy;
+ renderer->RenderPresent = GLES_RenderPresent;
+ renderer->DestroyTexture = GLES_DestroyTexture;
+ renderer->DestroyRenderer = GLES_DestroyRenderer;
+ renderer->info = GL_ES_RenderDriver.info;
+ renderer->driverdata = data;
+
+ renderer->info.flags = SDL_RENDERER_ACCELERATED;
+
+ if (GLES_LoadFunctions(data) < 0) {
+ GLES_DestroyRenderer(renderer);
+ return NULL;
+ }
+
+ data->context = SDL_GL_CreateContext(window);
+ if (!data->context) {
+ GLES_DestroyRenderer(renderer);
+ return NULL;
+ }
+ if (SDL_GL_MakeCurrent(window, data->context) < 0) {
+ GLES_DestroyRenderer(renderer);
+ return NULL;
+ }
+
+ if (flags & SDL_RENDERER_PRESENTVSYNC) {
+ SDL_GL_SetSwapInterval(1);
+ } else {
+ SDL_GL_SetSwapInterval(0);
+ }
+ if (SDL_GL_GetSwapInterval() > 0) {
+ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+ }
+
+#if SDL_VIDEO_DRIVER_PANDORA
+ data->GL_OES_draw_texture_supported = SDL_FALSE;
+ data->useDrawTexture = SDL_FALSE;
+#else
+ if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) {
+ data->GL_OES_draw_texture_supported = SDL_TRUE;
+ data->useDrawTexture = SDL_TRUE;
+ } else {
+ data->GL_OES_draw_texture_supported = SDL_FALSE;
+ data->useDrawTexture = SDL_FALSE;
+ }
+#endif
+
+ data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+ renderer->info.max_texture_width = value;
+ data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+ renderer->info.max_texture_height = value;
+
+ /* Set up parameters for rendering */
+ data->blendMode = -1;
+ data->glDisable(GL_DEPTH_TEST);
+ data->glDisable(GL_CULL_FACE);
+ data->updateSize = SDL_TRUE;
+
+ data->glEnableClientState(GL_VERTEX_ARRAY);
+ data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ return renderer;
+}
+
+static SDL_GLContext SDL_CurrentContext = NULL;
+
+static int
+GLES_ActivateRenderer(SDL_Renderer * renderer)
+{
+
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ SDL_Window *window = renderer->window;
+
+ if (SDL_CurrentContext != data->context) {
+ if (SDL_GL_MakeCurrent(window, data->context) < 0) {
+ return -1;
+ }
+ SDL_CurrentContext = data->context;
+ }
+ if (data->updateSize) {
+ int w, h;
+
+ SDL_GetWindowSize(window, &w, &h);
+ data->glMatrixMode(GL_PROJECTION);
+ data->glLoadIdentity();
+ data->glMatrixMode(GL_MODELVIEW);
+ data->glLoadIdentity();
+ data->glViewport(0, 0, w, h);
+ data->glOrthof(0.0, (GLfloat) w, (GLfloat) h, 0.0, 0.0, 1.0);
+ data->updateSize = SDL_FALSE;
+ }
+ return 0;
+}
+
+static void
+GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+
+ if (event->event == SDL_WINDOWEVENT_RESIZED) {
+ /* Rebind the context to the window area and update matrices */
+ SDL_CurrentContext = NULL;
+ data->updateSize = SDL_TRUE;
+ }
+}
+
+static __inline__ int
+power_of_2(int input)
+{
+ int value = 1;
+
+ while (value < input) {
+ value <<= 1;
+ }
+ return value;
+}
+
+static int
+GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *data;
+ GLint internalFormat;
+ GLenum format, type;
+ int texture_w, texture_h;
+ GLenum result;
+
+ GLES_ActivateRenderer(renderer);
+
+ switch (texture->format) {
+ case SDL_PIXELFORMAT_ABGR8888:
+ internalFormat = GL_RGBA;
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ SDL_SetError("Texture format %s not supported by OpenGL ES",
+ SDL_GetPixelFormatName(texture->format));
+ return -1;
+ }
+
+ data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ SDL_OutOfMemory();
+ return -1;
+ }
+
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
+ data->pixels = SDL_malloc(texture->h * data->pitch);
+ if (!data->pixels) {
+ SDL_OutOfMemory();
+ SDL_free(data);
+ return -1;
+ }
+ }
+
+ texture->driverdata = data;
+
+ renderdata->glGetError();
+ renderdata->glEnable(GL_TEXTURE_2D);
+ renderdata->glGenTextures(1, &data->texture);
+
+ data->type = GL_TEXTURE_2D;
+ /* no NPOV textures allowed in OpenGL ES (yet) */
+ texture_w = power_of_2(texture->w);
+ texture_h = power_of_2(texture->h);
+ data->texw = (GLfloat) texture->w / texture_w;
+ data->texh = (GLfloat) texture->h / texture_h;
+
+ data->format = format;
+ data->formattype = type;
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+
+ renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
+ texture_h, 0, format, type, NULL);
+ renderdata->glDisable(GL_TEXTURE_2D);
+
+ result = renderdata->glGetError();
+ if (result != GL_NO_ERROR) {
+ GLES_SetError("glTexImage2D()", result);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture,
+ int pitch)
+{
+ renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+}
+
+static int
+GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, const void *pixels, int pitch)
+{
+ GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+ GLenum result;
+ int bpp = SDL_BYTESPERPIXEL(texture->format);
+ void * temp_buffer;
+ void * temp_ptr;
+ int i;
+
+ GLES_ActivateRenderer(renderer);
+
+ renderdata->glGetError();
+ SetupTextureUpdate(renderdata, texture, pitch);
+ renderdata->glEnable(data->type);
+ renderdata->glBindTexture(data->type, data->texture);
+
+ if( rect->w * bpp == pitch ) {
+ temp_buffer = (void *)pixels; /* No need to reformat */
+ } else {
+ /* Reformatting of mem area required */
+ temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
+ temp_ptr = temp_buffer;
+ for (i = 0; i < rect->h; i++) {
+ SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
+ temp_ptr += rect->w * bpp;
+ pixels += pitch;
+ }
+ }
+
+ renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
+ rect->h, data->format, data->formattype,
+ temp_buffer);
+
+ if( temp_buffer != pixels ) {
+ SDL_free(temp_buffer);
+ }
+
+ renderdata->glDisable(data->type);
+ result = renderdata->glGetError();
+ if (result != GL_NO_ERROR) {
+ GLES_SetError("glTexSubImage2D()", result);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch)
+{
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+
+ *pixels =
+ (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
+ rect->x * SDL_BYTESPERPIXEL(texture->format));
+ *pitch = data->pitch;
+ return 0;
+}
+
+static void
+GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+
+ GLES_ActivateRenderer(renderer);
+
+ SetupTextureUpdate(renderdata, texture, data->pitch);
+ renderdata->glEnable(data->type);
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glTexSubImage2D(data->type, 0, 0, 0, texture->w,
+ texture->h, data->format, data->formattype,
+ data->pixels);
+ renderdata->glDisable(data->type);
+}
+
+static void
+GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
+{
+ if (blendMode != data->blendMode) {
+ switch (blendMode) {
+ case SDL_BLENDMODE_NONE:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ data->glDisable(GL_BLEND);
+ break;
+ case SDL_BLENDMODE_BLEND:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ data->glEnable(GL_BLEND);
+ data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case SDL_BLENDMODE_ADD:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ data->glEnable(GL_BLEND);
+ data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ break;
+ case SDL_BLENDMODE_MOD:
+ data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ data->glEnable(GL_BLEND);
+ data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+ break;
+ }
+ data->blendMode = blendMode;
+ }
+}
+
+static int
+GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ int i;
+ GLshort *vertices;
+
+ GLES_ActivateRenderer(renderer);
+
+ GLES_SetBlendMode(data, renderer->blendMode);
+
+ data->glColor4f((GLfloat) renderer->r * inv255f,
+ (GLfloat) renderer->g * inv255f,
+ (GLfloat) renderer->b * inv255f,
+ (GLfloat) renderer->a * inv255f);
+
+ vertices = SDL_stack_alloc(GLshort, count*2);
+ for (i = 0; i < count; ++i) {
+ vertices[2*i+0] = (GLshort)points[i].x;
+ vertices[2*i+1] = (GLshort)points[i].y;
+ }
+ data->glVertexPointer(2, GL_SHORT, 0, vertices);
+ data->glDrawArrays(GL_POINTS, 0, count);
+ SDL_stack_free(vertices);
+
+ return 0;
+}
+
+static int
+GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ int i;
+ GLshort *vertices;
+
+ GLES_ActivateRenderer(renderer);
+
+ GLES_SetBlendMode(data, renderer->blendMode);
+
+ data->glColor4f((GLfloat) renderer->r * inv255f,
+ (GLfloat) renderer->g * inv255f,
+ (GLfloat) renderer->b * inv255f,
+ (GLfloat) renderer->a * inv255f);
+
+ vertices = SDL_stack_alloc(GLshort, count*2);
+ for (i = 0; i < count; ++i) {
+ vertices[2*i+0] = (GLshort)points[i].x;
+ vertices[2*i+1] = (GLshort)points[i].y;
+ }
+ data->glVertexPointer(2, GL_SHORT, 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 */
+ --count;
+ data->glDrawArrays(GL_LINE_LOOP, 0, count);
+ } else {
+ data->glDrawArrays(GL_LINE_STRIP, 0, count);
+ }
+ SDL_stack_free(vertices);
+
+ return 0;
+}
+
+static int
+GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+ int count)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ int i;
+
+ GLES_ActivateRenderer(renderer);
+
+ GLES_SetBlendMode(data, renderer->blendMode);
+
+ data->glColor4f((GLfloat) renderer->r * inv255f,
+ (GLfloat) renderer->g * inv255f,
+ (GLfloat) renderer->b * inv255f,
+ (GLfloat) renderer->a * inv255f);
+
+ for (i = 0; i < count; ++i) {
+ const SDL_Rect *rect = rects[i];
+ GLshort minx = rect->x;
+ GLshort maxx = rect->x + rect->w;
+ GLshort miny = rect->y;
+ GLshort maxy = rect->y + rect->h;
+ GLshort vertices[8];
+ vertices[0] = minx;
+ vertices[1] = miny;
+ vertices[2] = maxx;
+ vertices[3] = miny;
+ vertices[4] = minx;
+ vertices[5] = maxy;
+ vertices[6] = maxx;
+ vertices[7] = maxy;
+
+ data->glVertexPointer(2, GL_SHORT, 0, vertices);
+ data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+
+ return 0;
+}
+
+static int
+GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_Rect * dstrect)
+{
+
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
+ int minx, miny, maxx, maxy;
+ GLfloat minu, maxu, minv, maxv;
+ int i;
+ void *temp_buffer; /* used for reformatting dirty rect pixels */
+ void *temp_ptr;
+
+ GLES_ActivateRenderer(renderer);
+
+ data->glEnable(GL_TEXTURE_2D);
+
+ data->glBindTexture(texturedata->type, texturedata->texture);
+
+ if (texture->modMode) {
+ data->glColor4f((GLfloat) texture->r * inv255f,
+ (GLfloat) texture->g * inv255f,
+ (GLfloat) texture->b * inv255f,
+ (GLfloat) texture->a * inv255f);
+ } else {
+ data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ GLES_SetBlendMode(data, texture->blendMode);
+
+ if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
+ /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
+ GLint cropRect[4];
+ int w, h;
+ SDL_Window *window = renderer->window;
+
+ SDL_GetWindowSize(window, &w, &h);
+ cropRect[0] = srcrect->x;
+ cropRect[1] = srcrect->y + srcrect->h;
+ cropRect[2] = srcrect->w;
+ cropRect[3] = -srcrect->h;
+ data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
+ cropRect);
+ data->glDrawTexiOES(dstrect->x, h - dstrect->y - dstrect->h, 0,
+ dstrect->w, dstrect->h);
+ } else {
+
+ minx = dstrect->x;
+ miny = dstrect->y;
+ maxx = dstrect->x + dstrect->w;
+ maxy = dstrect->y + dstrect->h;
+
+ minu = (GLfloat) srcrect->x / texture->w;
+ minu *= texturedata->texw;
+ maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
+ maxu *= texturedata->texw;
+ minv = (GLfloat) srcrect->y / texture->h;
+ minv *= texturedata->texh;
+ maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
+ maxv *= texturedata->texh;
+
+ GLshort vertices[8];
+ GLfloat texCoords[8];
+
+ vertices[0] = minx;
+ vertices[1] = miny;
+ vertices[2] = maxx;
+ vertices[3] = miny;
+ vertices[4] = minx;
+ vertices[5] = maxy;
+ vertices[6] = maxx;
+ vertices[7] = maxy;
+
+ texCoords[0] = minu;
+ texCoords[1] = minv;
+ texCoords[2] = maxu;
+ texCoords[3] = minv;
+ texCoords[4] = minu;
+ texCoords[5] = maxv;
+ texCoords[6] = maxu;
+ texCoords[7] = maxv;
+
+ data->glVertexPointer(2, GL_SHORT, 0, vertices);
+ data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+
+ data->glDisable(GL_TEXTURE_2D);
+
+ return 0;
+}
+
+static void
+GLES_RenderPresent(SDL_Renderer * renderer)
+{
+ GLES_ActivateRenderer(renderer);
+
+ SDL_GL_SwapWindow(renderer->window);
+}
+
+static void
+GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+
+ GLES_ActivateRenderer(renderer);
+
+ if (!data) {
+ return;
+ }
+ if (data->texture) {
+ glDeleteTextures(1, &data->texture);
+ }
+ if (data->pixels) {
+ SDL_free(data->pixels);
+ }
+ SDL_free(data);
+ texture->driverdata = NULL;
+}
+
+static void
+GLES_DestroyRenderer(SDL_Renderer * renderer)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+
+ if (data) {
+ if (data->context) {
+ SDL_GL_DeleteContext(data->context);
+ }
+ SDL_free(data);
+ }
+ SDL_free(renderer);
+}
+
+#endif /* SDL_VIDEO_RENDER_OGL_ES */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/render/opengles/SDL_renderer_gles.c Sat Feb 05 11:54:46 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,748 +0,0 @@
-/*
- SDL - Simple DirectMedia Layer
- Copyright (C) 1997-2010 Sam Lantinga
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- Sam Lantinga
- slouken@libsdl.org
-*/
-#include "SDL_config.h"
-
-#if SDL_VIDEO_RENDER_OGL_ES
-
-#include "SDL_opengles.h"
-#include "../SDL_sysrender.h"
-
-#if defined(SDL_VIDEO_DRIVER_PANDORA)
-
-/* Empty function stub to get OpenGL ES 1.x support without */
-/* OpenGL ES extension GL_OES_draw_texture supported */
-GL_API void GL_APIENTRY
-glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height)
-{
- return;
-}
-
-#endif /* PANDORA */
-
-/* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */
-
-/* Used to re-create the window with OpenGL capability */
-extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
-
-static const float inv255f = 1.0f / 255.0f;
-
-static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
-static void GLES_WindowEvent(SDL_Renderer * renderer,
- const SDL_WindowEvent *event);
-static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, const void *pixels,
- int pitch);
-static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch);
-static void GLES_UnlockTexture(SDL_Renderer * renderer,
- SDL_Texture * texture);
-static int GLES_RenderDrawPoints(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int GLES_RenderDrawLines(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int GLES_RenderFillRects(SDL_Renderer * renderer,
- const SDL_Rect ** rects, int count);
-static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect,
- const SDL_Rect * dstrect);
-static void GLES_RenderPresent(SDL_Renderer * renderer);
-static void GLES_DestroyTexture(SDL_Renderer * renderer,
- SDL_Texture * texture);
-static void GLES_DestroyRenderer(SDL_Renderer * renderer);
-
-
-SDL_RenderDriver GL_ES_RenderDriver = {
- GLES_CreateRenderer,
- {
- "opengl_es",
- (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
- 1,
- {SDL_PIXELFORMAT_ABGR8888},
- 0,
- 0}
-};
-
-typedef struct
-{
- SDL_GLContext context;
- SDL_bool updateSize;
- int blendMode;
-
-#ifndef APIENTRY
-#define APIENTRY
-#endif
-
- SDL_bool useDrawTexture;
- SDL_bool GL_OES_draw_texture_supported;
-
- /* OpenGL ES functions */
-#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
-#include "../../video/SDL_glesfuncs.h"
-#undef SDL_PROC
-
-} GLES_RenderData;
-
-typedef struct
-{
- GLuint texture;
- GLenum type;
- GLfloat texw;
- GLfloat texh;
- GLenum format;
- GLenum formattype;
- void *pixels;
- int pitch;
-} GLES_TextureData;
-
-static void
-GLES_SetError(const char *prefix, GLenum result)
-{
- const char *error;
-
- switch (result) {
- case GL_NO_ERROR:
- error = "GL_NO_ERROR";
- break;
- case GL_INVALID_ENUM:
- error = "GL_INVALID_ENUM";
- break;
- case GL_INVALID_VALUE:
- error = "GL_INVALID_VALUE";
- break;
- case GL_INVALID_OPERATION:
- error = "GL_INVALID_OPERATION";
- break;
- case GL_STACK_OVERFLOW:
- error = "GL_STACK_OVERFLOW";
- break;
- case GL_STACK_UNDERFLOW:
- error = "GL_STACK_UNDERFLOW";
- break;
- case GL_OUT_OF_MEMORY:
- error = "GL_OUT_OF_MEMORY";
- break;
- default:
- error = "UNKNOWN";
- break;
- }
- SDL_SetError("%s: %s", prefix, error);
-}
-
-static int
-GLES_LoadFunctions(GLES_RenderData * data)
-{
-
-#define SDL_PROC(ret,func,params) \
- data->func = func;
-#include "../../video/SDL_glesfuncs.h"
-#undef SDL_PROC
-
- return 0;
-}
-
-SDL_Renderer *
-GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
-{
-
- SDL_Renderer *renderer;
- GLES_RenderData *data;
- GLint value;
- Uint32 window_flags;
-
- window_flags = SDL_GetWindowFlags(window);
- if (!(window_flags & SDL_WINDOW_OPENGL)) {
- if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
- return NULL;
- }
- }
-
- renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
- if (!renderer) {
- SDL_OutOfMemory();
- return NULL;
- }
-
- data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- GLES_DestroyRenderer(renderer);
- SDL_OutOfMemory();
- return NULL;
- }
-
- renderer->WindowEvent = GLES_WindowEvent;
- renderer->CreateTexture = GLES_CreateTexture;
- renderer->UpdateTexture = GLES_UpdateTexture;
- renderer->LockTexture = GLES_LockTexture;
- renderer->UnlockTexture = GLES_UnlockTexture;
- renderer->RenderDrawPoints = GLES_RenderDrawPoints;
- renderer->RenderDrawLines = GLES_RenderDrawLines;
- renderer->RenderFillRects = GLES_RenderFillRects;
- renderer->RenderCopy = GLES_RenderCopy;
- renderer->RenderPresent = GLES_RenderPresent;
- renderer->DestroyTexture = GLES_DestroyTexture;
- renderer->DestroyRenderer = GLES_DestroyRenderer;
- renderer->info = GL_ES_RenderDriver.info;
- renderer->driverdata = data;
-
- renderer->info.flags = SDL_RENDERER_ACCELERATED;
-
- if (GLES_LoadFunctions(data) < 0) {
- GLES_DestroyRenderer(renderer);
- return NULL;
- }
-
- data->context = SDL_GL_CreateContext(window);
- if (!data->context) {
- GLES_DestroyRenderer(renderer);
- return NULL;
- }
- if (SDL_GL_MakeCurrent(window, data->context) < 0) {
- GLES_DestroyRenderer(renderer);
- return NULL;
- }
-
- if (flags & SDL_RENDERER_PRESENTVSYNC) {
- SDL_GL_SetSwapInterval(1);
- } else {
- SDL_GL_SetSwapInterval(0);
- }
- if (SDL_GL_GetSwapInterval() > 0) {
- renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
- }
-
-#if SDL_VIDEO_DRIVER_PANDORA
- data->GL_OES_draw_texture_supported = SDL_FALSE;
- data->useDrawTexture = SDL_FALSE;
-#else
- if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) {
- data->GL_OES_draw_texture_supported = SDL_TRUE;
- data->useDrawTexture = SDL_TRUE;
- } else {
- data->GL_OES_draw_texture_supported = SDL_FALSE;
- data->useDrawTexture = SDL_FALSE;
- }
-#endif
-
- data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
- renderer->info.max_texture_width = value;
- data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
- renderer->info.max_texture_height = value;
-
- /* Set up parameters for rendering */
- data->blendMode = -1;
- data->glDisable(GL_DEPTH_TEST);
- data->glDisable(GL_CULL_FACE);
- data->updateSize = SDL_TRUE;
-
- data->glEnableClientState(GL_VERTEX_ARRAY);
- data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- return renderer;
-}
-
-static SDL_GLContext SDL_CurrentContext = NULL;
-
-static int
-GLES_ActivateRenderer(SDL_Renderer * renderer)
-{
-
- GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
- SDL_Window *window = renderer->window;
-
- if (SDL_CurrentContext != data->context) {
- if (SDL_GL_MakeCurrent(window, data->context) < 0) {
- return -1;
- }
- SDL_CurrentContext = data->context;
- }
- if (data->updateSize) {
- int w, h;
-
- SDL_GetWindowSize(window, &w, &h);
- data->glMatrixMode(GL_PROJECTION);
- data->glLoadIdentity();
- data->glMatrixMode(GL_MODELVIEW);
- data->glLoadIdentity();
- data->glViewport(0, 0, w, h);
- data->glOrthof(0.0, (GLfloat) w, (GLfloat) h, 0.0, 0.0, 1.0);
- data->updateSize = SDL_FALSE;
- }
- return 0;
-}
-
-static void
-GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
-{
- GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
- if (event->event == SDL_WINDOWEVENT_RESIZED) {
- /* Rebind the context to the window area and update matrices */
- SDL_CurrentContext = NULL;
- data->updateSize = SDL_TRUE;
- }
-}
-
-static __inline__ int
-power_of_2(int input)
-{
- int value = 1;
-
- while (value < input) {
- value <<= 1;
- }
- return value;
-}
-
-static int
-GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
- GLES_TextureData *data;
- GLint internalFormat;
- GLenum format, type;
- int texture_w, texture_h;
- GLenum result;
-
- GLES_ActivateRenderer(renderer);
-
- switch (texture->format) {
- case SDL_PIXELFORMAT_ABGR8888:
- internalFormat = GL_RGBA;
- format = GL_RGBA;
- type = GL_UNSIGNED_BYTE;
- break;
- default:
- SDL_SetError("Texture format %s not supported by OpenGL ES",
- SDL_GetPixelFormatName(texture->format));
- return -1;
- }
-
- data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- SDL_OutOfMemory();
- return -1;
- }
-
- if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
- data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
- data->pixels = SDL_malloc(texture->h * data->pitch);
- if (!data->pixels) {
- SDL_OutOfMemory();
- SDL_free(data);
- return -1;
- }
- }
-
- texture->driverdata = data;
-
- renderdata->glGetError();
- renderdata->glEnable(GL_TEXTURE_2D);
- renderdata->glGenTextures(1, &data->texture);
-
- data->type = GL_TEXTURE_2D;
- /* no NPOV textures allowed in OpenGL ES (yet) */
- texture_w = power_of_2(texture->w);
- texture_h = power_of_2(texture->h);
- data->texw = (GLfloat) texture->w / texture_w;
- data->texh = (GLfloat) texture->h / texture_h;
-
- data->format = format;
- data->formattype = type;
- renderdata->glBindTexture(data->type, data->texture);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
- GL_LINEAR);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_EDGE);
- renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_EDGE);
-
- renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
- texture_h, 0, format, type, NULL);
- renderdata->glDisable(GL_TEXTURE_2D);
-
- result = renderdata->glGetError();
- if (result != GL_NO_ERROR) {
- GLES_SetError("glTexImage2D()", result);
- return -1;
- }
- return 0;
-}
-
-static void
-SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture,
- int pitch)
-{
- renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-}
-
-static int
-GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, const void *pixels, int pitch)
-{
- GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
- GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
- GLenum result;
- int bpp = SDL_BYTESPERPIXEL(texture->format);
- void * temp_buffer;
- void * temp_ptr;
- int i;
-
- GLES_ActivateRenderer(renderer);
-
- renderdata->glGetError();
- SetupTextureUpdate(renderdata, texture, pitch);
- renderdata->glEnable(data->type);
- renderdata->glBindTexture(data->type, data->texture);
-
- if( rect->w * bpp == pitch ) {
- temp_buffer = (void *)pixels; /* No need to reformat */
- } else {
- /* Reformatting of mem area required */
- temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
- temp_ptr = temp_buffer;
- for (i = 0; i < rect->h; i++) {
- SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
- temp_ptr += rect->w * bpp;
- pixels += pitch;
- }
- }
-
- renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
- rect->h, data->format, data->formattype,
- temp_buffer);
-
- if( temp_buffer != pixels ) {
- SDL_free(temp_buffer);
- }
-
- renderdata->glDisable(data->type);
- result = renderdata->glGetError();
- if (result != GL_NO_ERROR) {
- GLES_SetError("glTexSubImage2D()", result);
- return -1;
- }
- return 0;
-}
-
-static int
-GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch)
-{
- GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
-
- *pixels =
- (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
- rect->x * SDL_BYTESPERPIXEL(texture->format));
- *pitch = data->pitch;
- return 0;
-}
-
-static void
-GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
- GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
-
- GLES_ActivateRenderer(renderer);
-
- SetupTextureUpdate(renderdata, texture, data->pitch);
- renderdata->glEnable(data->type);
- renderdata->glBindTexture(data->type, data->texture);
- renderdata->glTexSubImage2D(data->type, 0, 0, 0, texture->w,
- texture->h, data->format, data->formattype,
- data->pixels);
- renderdata->glDisable(data->type);
-}
-
-static void
-GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
-{
- if (blendMode != data->blendMode) {
- switch (blendMode) {
- case SDL_BLENDMODE_NONE:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- data->glDisable(GL_BLEND);
- break;
- case SDL_BLENDMODE_BLEND:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- data->glEnable(GL_BLEND);
- data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- break;
- case SDL_BLENDMODE_ADD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- data->glEnable(GL_BLEND);
- data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- break;
- case SDL_BLENDMODE_MOD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- data->glEnable(GL_BLEND);
- data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
- break;
- }
- data->blendMode = blendMode;
- }
-}
-
-static int
-GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
- int i;
- GLshort *vertices;
-
- GLES_ActivateRenderer(renderer);
-
- GLES_SetBlendMode(data, renderer->blendMode);
-
- data->glColor4f((GLfloat) renderer->r * inv255f,
- (GLfloat) renderer->g * inv255f,
- (GLfloat) renderer->b * inv255f,
- (GLfloat) renderer->a * inv255f);
-
- vertices = SDL_stack_alloc(GLshort, count*2);
- for (i = 0; i < count; ++i) {
- vertices[2*i+0] = (GLshort)points[i].x;
- vertices[2*i+1] = (GLshort)points[i].y;
- }
- data->glVertexPointer(2, GL_SHORT, 0, vertices);
- data->glDrawArrays(GL_POINTS, 0, count);
- SDL_stack_free(vertices);
-
- return 0;
-}
-
-static int
-GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
- int i;
- GLshort *vertices;
-
- GLES_ActivateRenderer(renderer);
-
- GLES_SetBlendMode(data, renderer->blendMode);
-
- data->glColor4f((GLfloat) renderer->r * inv255f,
- (GLfloat) renderer->g * inv255f,
- (GLfloat) renderer->b * inv255f,
- (GLfloat) renderer->a * inv255f);
-
- vertices = SDL_stack_alloc(GLshort, count*2);
- for (i = 0; i < count; ++i) {
- vertices[2*i+0] = (GLshort)points[i].x;
- vertices[2*i+1] = (GLshort)points[i].y;
- }
- data->glVertexPointer(2, GL_SHORT, 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 */
- --count;
- data->glDrawArrays(GL_LINE_LOOP, 0, count);
- } else {
- data->glDrawArrays(GL_LINE_STRIP, 0, count);
- }
- SDL_stack_free(vertices);
-
- return 0;
-}
-
-static int
-GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
- int count)
-{
- GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
- int i;
-
- GLES_ActivateRenderer(renderer);
-
- GLES_SetBlendMode(data, renderer->blendMode);
-
- data->glColor4f((GLfloat) renderer->r * inv255f,
- (GLfloat) renderer->g * inv255f,
- (GLfloat) renderer->b * inv255f,
- (GLfloat) renderer->a * inv255f);
-
- for (i = 0; i < count; ++i) {
- const SDL_Rect *rect = rects[i];
- GLshort minx = rect->x;
- GLshort maxx = rect->x + rect->w;
- GLshort miny = rect->y;
- GLshort maxy = rect->y + rect->h;
- GLshort vertices[8];
- vertices[0] = minx;
- vertices[1] = miny;
- vertices[2] = maxx;
- vertices[3] = miny;
- vertices[4] = minx;
- vertices[5] = maxy;
- vertices[6] = maxx;
- vertices[7] = maxy;
-
- data->glVertexPointer(2, GL_SHORT, 0, vertices);
- data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- }
-
- return 0;
-}
-
-static int
-GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_Rect * dstrect)
-{
-
- GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
- GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
- int minx, miny, maxx, maxy;
- GLfloat minu, maxu, minv, maxv;
- int i;
- void *temp_buffer; /* used for reformatting dirty rect pixels */
- void *temp_ptr;
-
- GLES_ActivateRenderer(renderer);
-
- data->glEnable(GL_TEXTURE_2D);
-
- data->glBindTexture(texturedata->type, texturedata->texture);
-
- if (texture->modMode) {
- data->glColor4f((GLfloat) texture->r * inv255f,
- (GLfloat) texture->g * inv255f,
- (GLfloat) texture->b * inv255f,
- (GLfloat) texture->a * inv255f);
- } else {
- data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- }
-
- GLES_SetBlendMode(data, texture->blendMode);
-
- if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
- /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
- GLint cropRect[4];
- int w, h;
- SDL_Window *window = renderer->window;
-
- SDL_GetWindowSize(window, &w, &h);
- cropRect[0] = srcrect->x;
- cropRect[1] = srcrect->y + srcrect->h;
- cropRect[2] = srcrect->w;
- cropRect[3] = -srcrect->h;
- data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
- cropRect);
- data->glDrawTexiOES(dstrect->x, h - dstrect->y - dstrect->h, 0,
- dstrect->w, dstrect->h);
- } else {
-
- minx = dstrect->x;
- miny = dstrect->y;
- maxx = dstrect->x + dstrect->w;
- maxy = dstrect->y + dstrect->h;
-
- minu = (GLfloat) srcrect->x / texture->w;
- minu *= texturedata->texw;
- maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
- maxu *= texturedata->texw;
- minv = (GLfloat) srcrect->y / texture->h;
- minv *= texturedata->texh;
- maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
- maxv *= texturedata->texh;
-
- GLshort vertices[8];
- GLfloat texCoords[8];
-
- vertices[0] = minx;
- vertices[1] = miny;
- vertices[2] = maxx;
- vertices[3] = miny;
- vertices[4] = minx;
- vertices[5] = maxy;
- vertices[6] = maxx;
- vertices[7] = maxy;
-
- texCoords[0] = minu;
- texCoords[1] = minv;
- texCoords[2] = maxu;
- texCoords[3] = minv;
- texCoords[4] = minu;
- texCoords[5] = maxv;
- texCoords[6] = maxu;
- texCoords[7] = maxv;
-
- data->glVertexPointer(2, GL_SHORT, 0, vertices);
- data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
- data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- }
-
- data->glDisable(GL_TEXTURE_2D);
-
- return 0;
-}
-
-static void
-GLES_RenderPresent(SDL_Renderer * renderer)
-{
- GLES_ActivateRenderer(renderer);
-
- SDL_GL_SwapWindow(renderer->window);
-}
-
-static void
-GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
-
- GLES_ActivateRenderer(renderer);
-
- if (!data) {
- return;
- }
- if (data->texture) {
- glDeleteTextures(1, &data->texture);
- }
- if (data->pixels) {
- SDL_free(data->pixels);
- }
- SDL_free(data);
- texture->driverdata = NULL;
-}
-
-static void
-GLES_DestroyRenderer(SDL_Renderer * renderer)
-{
- GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
- if (data) {
- if (data->context) {
- SDL_GL_DeleteContext(data->context);
- }
- SDL_free(data);
- }
- SDL_free(renderer);
-}
-
-#endif /* SDL_VIDEO_RENDER_OGL_ES */
-
-/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/render/software/SDL_render_sw.c Sat Feb 05 12:01:11 2011 -0800
@@ -0,0 +1,418 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2010 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "../SDL_sysrender.h"
+#include "../../video/SDL_pixels_c.h"
+
+#include "SDL_draw.h"
+#include "SDL_blendfillrect.h"
+#include "SDL_blendline.h"
+#include "SDL_blendpoint.h"
+#include "SDL_drawline.h"
+#include "SDL_drawpoint.h"
+
+
+/* SDL surface based renderer implementation */
+
+static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
+static void SW_WindowEvent(SDL_Renderer * renderer,
+ const SDL_WindowEvent *event);
+static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int SW_SetTextureColorMod(SDL_Renderer * renderer,
+ SDL_Texture * texture);
+static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
+ SDL_Texture * texture);
+static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
+ SDL_Texture * texture);
+static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, const void *pixels,
+ int pitch);
+static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch);
+static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int SW_RenderDrawPoints(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int SW_RenderDrawLines(SDL_Renderer * renderer,
+ const SDL_Point * points, int count);
+static int SW_RenderFillRects(SDL_Renderer * renderer,
+ const SDL_Rect ** rects, int count);
+static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+ Uint32 format, void * pixels, int pitch);
+static void SW_RenderPresent(SDL_Renderer * renderer);
+static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static void SW_DestroyRenderer(SDL_Renderer * renderer);
+
+
+SDL_RenderDriver SW_RenderDriver = {
+ SW_CreateRenderer,
+ {
+ "software",
+ 0,
+ 8,
+ {
+ SDL_PIXELFORMAT_RGB555,
+ SDL_PIXELFORMAT_RGB565,
+ SDL_PIXELFORMAT_RGB888,
+ SDL_PIXELFORMAT_BGR888,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_RGBA8888,
+ SDL_PIXELFORMAT_ABGR8888,
+ SDL_PIXELFORMAT_BGRA8888
+ },
+ 0,
+ 0}
+};
+
+typedef struct
+{
+ SDL_bool updateSize;
+ SDL_Surface *surface;
+} SW_RenderData;
+
+
+SDL_Renderer *
+SW_CreateRendererForSurface(SDL_Surface * surface)
+{
+ SDL_Renderer *renderer;
+ SW_RenderData *data;
+
+ if (!surface) {
+ SDL_SetError("Can't create renderer for NULL surface");
+ return NULL;
+ }
+
+ renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+ if (!renderer) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ SW_DestroyRenderer(renderer);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+ data->surface = surface;
+
+ renderer->WindowEvent = SW_WindowEvent;
+ renderer->CreateTexture = SW_CreateTexture;
+ renderer->SetTextureColorMod = SW_SetTextureColorMod;
+ renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
+ renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
+ renderer->UpdateTexture = SW_UpdateTexture;
+ renderer->LockTexture = SW_LockTexture;
+ renderer->UnlockTexture = SW_UnlockTexture;
+ renderer->DestroyTexture = SW_DestroyTexture;
+ renderer->RenderDrawPoints = SW_RenderDrawPoints;
+ renderer->RenderDrawLines = SW_RenderDrawLines;
+ renderer->RenderFillRects = SW_RenderFillRects;
+ renderer->RenderCopy = SW_RenderCopy;
+ renderer->RenderReadPixels = SW_RenderReadPixels;
+ renderer->RenderPresent = SW_RenderPresent;
+ renderer->DestroyRenderer = SW_DestroyRenderer;
+ renderer->info = SW_RenderDriver.info;
+ renderer->driverdata = data;
+
+ return renderer;
+}
+
+SDL_Renderer *
+SW_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+ SDL_Surface *surface;
+
+ surface = SDL_GetWindowSurface(window);
+ if (!surface) {
+ return NULL;
+ }
+ return SW_CreateRendererForSurface(surface);
+}
+
+static SDL_Surface *
+SW_ActivateRenderer(SDL_Renderer * renderer)
+{
+ SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+ SDL_Window *window = renderer->window;
+
+ if (data->updateSize) {
+ data->surface = SDL_GetWindowSurface(window);
+ data->updateSize = SDL_FALSE;
+ }
+ return data->surface;
+}
+
+static void
+SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
+{
+ SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+
+ if (event->event == SDL_WINDOWEVENT_RESIZED) {
+ data->updateSize = SDL_TRUE;
+ }
+}
+
+static int
+SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ int bpp;
+ Uint32 Rmask, Gmask, Bmask, Amask;
+
+ if (!SDL_PixelFormatEnumToMasks
+ (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
+ SDL_SetError("Unknown texture format");
+ return -1;
+ }
+
+ texture->driverdata =
+ SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
+ Bmask, Amask);
+ SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
+ texture->b);
+ SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
+ SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
+
+ if (texture->access == SDL_TEXTUREACCESS_STATIC) {
+ SDL_SetSurfaceRLE(texture->driverdata, 1);
+ }
+
+ if (!texture->driverdata) {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+ return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
+ texture->b);
+}
+
+static int
+SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+ return SDL_SetSurfaceAlphaMod(surface, texture->a);
+}
+
+static int
+SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+ return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
+}
+
+static int
+SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, const void *pixels, int pitch)
+{
+ SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+ Uint8 *src, *dst;
+ int row;
+ size_t length;
+
+ src = (Uint8 *) pixels;
+ dst = (Uint8 *) surface->pixels +
+ rect->y * surface->pitch +
+ rect->x * surface->format->BytesPerPixel;
+ length = rect->w * surface->format->BytesPerPixel;
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, src, length);
+ src += pitch;
+ dst += surface->pitch;
+ }
+ return 0;
+}
+
+static int
+SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch)
+{
+ SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+
+ *pixels =
+ (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
+ rect->x * surface->format->BytesPerPixel);
+ *pitch = surface->pitch;
+ return 0;
+}
+
+static void
+SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+}
+
+static int
+SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ SDL_Surface *surface = SW_ActivateRenderer(renderer);
+
+ if (!surface) {
+ return -1;
+ }
+
+ /* Draw the points! */
+ if (renderer->blendMode == SDL_BLENDMODE_NONE) {
+ Uint32 color = SDL_MapRGBA(surface->format,
+ renderer->r, renderer->g, renderer->b,
+ renderer->a);
+
+ return SDL_DrawPoints(surface, points, count, color);
+ } else {
+ return SDL_BlendPoints(surface, points, count,
+ renderer->blendMode,
+ renderer->r, renderer->g, renderer->b,
+ renderer->a);
+ }
+}
+
+static int
+SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
+ int count)
+{
+ SDL_Surface *surface = SW_ActivateRenderer(renderer);
+
+ if (!surface) {
+ return -1;
+ }
+
+ /* Draw the lines! */
+ if (renderer->blendMode == SDL_BLENDMODE_NONE) {
+ Uint32 color = SDL_MapRGBA(surface->format,
+ renderer->r, renderer->g, renderer->b,
+ renderer->a);
+
+ return SDL_DrawLines(surface, points, count, color);
+ } else {
+ return SDL_BlendLines(surface, points, count,
+ renderer->blendMode,
+ renderer->r, renderer->g, renderer->b,
+ renderer->a);
+ }
+}
+
+static int
+SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+ int count)
+{
+ SDL_Surface *surface = SW_ActivateRenderer(renderer);
+
+ if (!surface) {
+ return -1;
+ }
+
+ if (renderer->blendMode == SDL_BLENDMODE_NONE) {
+ Uint32 color = SDL_MapRGBA(surface->format,
+ renderer->r, renderer->g, renderer->b,
+ renderer->a);
+ return SDL_FillRects(surface, rects, count, color);
+ } else {
+ return SDL_BlendFillRects(surface, rects, count,
+ renderer->blendMode,
+ renderer->r, renderer->g, renderer->b,
+ renderer->a);
+ }
+}
+
+static int
+SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * srcrect, const SDL_Rect * dstrect)
+{
+ SDL_Surface *surface = SW_ActivateRenderer(renderer);
+ SDL_Surface *src = (SDL_Surface *) texture->driverdata;
+ SDL_Rect final_rect = *dstrect;
+
+ if (!surface) {
+ return -1;
+ }
+ return SDL_BlitSurface(src, srcrect, surface, &final_rect);
+}
+
+static int
+SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+ Uint32 format, void * pixels, int pitch)
+{
+ SDL_Surface *surface = SW_ActivateRenderer(renderer);
+ Uint32 src_format;
+ void *src_pixels;
+
+ if (!surface) {
+ return -1;
+ }
+
+ if (rect->x < 0 || rect->x+rect->w > surface->w ||
+ rect->y < 0 || rect->y+rect->h > surface->h) {
+ SDL_SetError("Tried to read outside of surface bounds");
+ return -1;
+ }
+
+ src_format = SDL_MasksToPixelFormatEnum(
+ surface->format->BitsPerPixel,
+ surface->format->Rmask, surface->format->Gmask,
+ surface->format->Bmask, surface->format->Amask);
+
+ src_pixels = (void*)((Uint8 *) surface->pixels +
+ rect->y * surface->pitch +
+ rect->x * surface->format->BytesPerPixel);
+
+ return SDL_ConvertPixels(rect->w, rect->h,
+ src_format, src_pixels, surface->pitch,
+ format, pixels, pitch);
+}
+
+static void
+SW_RenderPresent(SDL_Renderer * renderer)
+{
+ SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+ SDL_Window *window = renderer->window;
+
+ if (window) {
+ SDL_UpdateWindowSurface(window);
+ }
+}
+
+static void
+SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+
+ SDL_FreeSurface(surface);
+}
+
+static void
+SW_DestroyRenderer(SDL_Renderer * renderer)
+{
+ SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+
+ if (data) {
+ SDL_free(data);
+ }
+ SDL_free(renderer);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/render/software/SDL_render_sw_c.h Sat Feb 05 12:01:11 2011 -0800
@@ -0,0 +1,25 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2010 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+extern SDL_Renderer * SW_CreateRendererForSurface(SDL_Surface * surface);
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/render/software/SDL_renderer_sw.c Sat Feb 05 11:54:46 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,418 +0,0 @@
-/*
- SDL - Simple DirectMedia Layer
- Copyright (C) 1997-2010 Sam Lantinga
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- Sam Lantinga
- slouken@libsdl.org
-*/
-#include "SDL_config.h"
-
-#include "../SDL_sysrender.h"
-#include "../../video/SDL_pixels_c.h"
-
-#include "SDL_draw.h"
-#include "SDL_blendfillrect.h"
-#include "SDL_blendline.h"
-#include "SDL_blendpoint.h"
-#include "SDL_drawline.h"
-#include "SDL_drawpoint.h"
-
-
-/* SDL surface based renderer implementation */
-
-static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
-static void SW_WindowEvent(SDL_Renderer * renderer,
- const SDL_WindowEvent *event);
-static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int SW_SetTextureColorMod(SDL_Renderer * renderer,
- SDL_Texture * texture);
-static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
- SDL_Texture * texture);
-static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
- SDL_Texture * texture);
-static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, const void *pixels,
- int pitch);
-static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch);
-static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int SW_RenderDrawPoints(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int SW_RenderDrawLines(SDL_Renderer * renderer,
- const SDL_Point * points, int count);
-static int SW_RenderFillRects(SDL_Renderer * renderer,
- const SDL_Rect ** rects, int count);
-static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_Rect * dstrect);
-static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
- Uint32 format, void * pixels, int pitch);
-static void SW_RenderPresent(SDL_Renderer * renderer);
-static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static void SW_DestroyRenderer(SDL_Renderer * renderer);
-
-
-SDL_RenderDriver SW_RenderDriver = {
- SW_CreateRenderer,
- {
- "software",
- 0,
- 8,
- {
- SDL_PIXELFORMAT_RGB555,
- SDL_PIXELFORMAT_RGB565,
- SDL_PIXELFORMAT_RGB888,
- SDL_PIXELFORMAT_BGR888,
- SDL_PIXELFORMAT_ARGB8888,
- SDL_PIXELFORMAT_RGBA8888,
- SDL_PIXELFORMAT_ABGR8888,
- SDL_PIXELFORMAT_BGRA8888
- },
- 0,
- 0}
-};
-
-typedef struct
-{
- SDL_bool updateSize;
- SDL_Surface *surface;
-} SW_RenderData;
-
-
-SDL_Renderer *
-SW_CreateRendererForSurface(SDL_Surface * surface)
-{
- SDL_Renderer *renderer;
- SW_RenderData *data;
-
- if (!surface) {
- SDL_SetError("Can't create renderer for NULL surface");
- return NULL;
- }
-
- renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
- if (!renderer) {
- SDL_OutOfMemory();
- return NULL;
- }
-
- data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
- if (!data) {
- SW_DestroyRenderer(renderer);
- SDL_OutOfMemory();
- return NULL;
- }
- data->surface = surface;
-
- renderer->WindowEvent = SW_WindowEvent;
- renderer->CreateTexture = SW_CreateTexture;
- renderer->SetTextureColorMod = SW_SetTextureColorMod;
- renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
- renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
- renderer->UpdateTexture = SW_UpdateTexture;
- renderer->LockTexture = SW_LockTexture;
- renderer->UnlockTexture = SW_UnlockTexture;
- renderer->DestroyTexture = SW_DestroyTexture;
- renderer->RenderDrawPoints = SW_RenderDrawPoints;
- renderer->RenderDrawLines = SW_RenderDrawLines;
- renderer->RenderFillRects = SW_RenderFillRects;
- renderer->RenderCopy = SW_RenderCopy;
- renderer->RenderReadPixels = SW_RenderReadPixels;
- renderer->RenderPresent = SW_RenderPresent;
- renderer->DestroyRenderer = SW_DestroyRenderer;
- renderer->info = SW_RenderDriver.info;
- renderer->driverdata = data;
-
- return renderer;
-}
-
-SDL_Renderer *
-SW_CreateRenderer(SDL_Window * window, Uint32 flags)
-{
- SDL_Surface *surface;
-
- surface = SDL_GetWindowSurface(window);
- if (!surface) {
- return NULL;
- }
- return SW_CreateRendererForSurface(surface);
-}
-
-static SDL_Surface *
-SW_ActivateRenderer(SDL_Renderer * renderer)
-{
- SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
- SDL_Window *window = renderer->window;
-
- if (data->updateSize) {
- data->surface = SDL_GetWindowSurface(window);
- data->updateSize = SDL_FALSE;
- }
- return data->surface;
-}
-
-static void
-SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
-{
- SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
-
- if (event->event == SDL_WINDOWEVENT_RESIZED) {
- data->updateSize = SDL_TRUE;
- }
-}
-
-static int
-SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- int bpp;
- Uint32 Rmask, Gmask, Bmask, Amask;
-
- if (!SDL_PixelFormatEnumToMasks
- (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
- SDL_SetError("Unknown texture format");
- return -1;
- }
-
- texture->driverdata =
- SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
- Bmask, Amask);
- SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
- texture->b);
- SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
- SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
-
- if (texture->access == SDL_TEXTUREACCESS_STATIC) {
- SDL_SetSurfaceRLE(texture->driverdata, 1);
- }
-
- if (!texture->driverdata) {
- return -1;
- }
- return 0;
-}
-
-static int
-SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
- return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
- texture->b);
-}
-
-static int
-SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
- return SDL_SetSurfaceAlphaMod(surface, texture->a);
-}
-
-static int
-SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
- return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
-}
-
-static int
-SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, const void *pixels, int pitch)
-{
- SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
- Uint8 *src, *dst;
- int row;
- size_t length;
-
- src = (Uint8 *) pixels;
- dst = (Uint8 *) surface->pixels +
- rect->y * surface->pitch +
- rect->x * surface->format->BytesPerPixel;
- length = rect->w * surface->format->BytesPerPixel;
- for (row = 0; row < rect->h; ++row) {
- SDL_memcpy(dst, src, length);
- src += pitch;
- dst += surface->pitch;
- }
- return 0;
-}
-
-static int
-SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * rect, void **pixels, int *pitch)
-{
- SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
-
- *pixels =
- (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
- rect->x * surface->format->BytesPerPixel);
- *pitch = surface->pitch;
- return 0;
-}
-
-static void
-SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
-}
-
-static int
-SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- SDL_Surface *surface = SW_ActivateRenderer(renderer);
-
- if (!surface) {
- return -1;
- }
-
- /* Draw the points! */
- if (renderer->blendMode == SDL_BLENDMODE_NONE) {
- Uint32 color = SDL_MapRGBA(surface->format,
- renderer->r, renderer->g, renderer->b,
- renderer->a);
-
- return SDL_DrawPoints(surface, points, count, color);
- } else {
- return SDL_BlendPoints(surface, points, count,
- renderer->blendMode,
- renderer->r, renderer->g, renderer->b,
- renderer->a);
- }
-}
-
-static int
-SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
- int count)
-{
- SDL_Surface *surface = SW_ActivateRenderer(renderer);
-
- if (!surface) {
- return -1;
- }
-
- /* Draw the lines! */
- if (renderer->blendMode == SDL_BLENDMODE_NONE) {
- Uint32 color = SDL_MapRGBA(surface->format,
- renderer->r, renderer->g, renderer->b,
- renderer->a);
-
- return SDL_DrawLines(surface, points, count, color);
- } else {
- return SDL_BlendLines(surface, points, count,
- renderer->blendMode,
- renderer->r, renderer->g, renderer->b,
- renderer->a);
- }
-}
-
-static int
-SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
- int count)
-{
- SDL_Surface *surface = SW_ActivateRenderer(renderer);
-
- if (!surface) {
- return -1;
- }
-
- if (renderer->blendMode == SDL_BLENDMODE_NONE) {
- Uint32 color = SDL_MapRGBA(surface->format,
- renderer->r, renderer->g, renderer->b,
- renderer->a);
- return SDL_FillRects(surface, rects, count, color);
- } else {
- return SDL_BlendFillRects(surface, rects, count,
- renderer->blendMode,
- renderer->r, renderer->g, renderer->b,
- renderer->a);
- }
-}
-
-static int
-SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
- const SDL_Rect * srcrect, const SDL_Rect * dstrect)
-{
- SDL_Surface *surface = SW_ActivateRenderer(renderer);
- SDL_Surface *src = (SDL_Surface *) texture->driverdata;
- SDL_Rect final_rect = *dstrect;
-
- if (!surface) {
- return -1;
- }
- return SDL_BlitSurface(src, srcrect, surface, &final_rect);
-}
-
-static int
-SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
- Uint32 format, void * pixels, int pitch)
-{
- SDL_Surface *surface = SW_ActivateRenderer(renderer);
- Uint32 src_format;
- void *src_pixels;
-
- if (!surface) {
- return -1;
- }
-
- if (rect->x < 0 || rect->x+rect->w > surface->w ||
- rect->y < 0 || rect->y+rect->h > surface->h) {
- SDL_SetError("Tried to read outside of surface bounds");
- return -1;
- }
-
- src_format = SDL_MasksToPixelFormatEnum(
- surface->format->BitsPerPixel,
- surface->format->Rmask, surface->format->Gmask,
- surface->format->Bmask, surface->format->Amask);
-
- src_pixels = (void*)((Uint8 *) surface->pixels +
- rect->y * surface->pitch +
- rect->x * surface->format->BytesPerPixel);
-
- return SDL_ConvertPixels(rect->w, rect->h,
- src_format, src_pixels, surface->pitch,
- format, pixels, pitch);
-}
-
-static void
-SW_RenderPresent(SDL_Renderer * renderer)
-{
- SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
- SDL_Window *window = renderer->window;
-
- if (window) {
- SDL_UpdateWindowSurface(window);
- }
-}
-
-static void
-SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
- SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
-
- SDL_FreeSurface(surface);
-}
-
-static void
-SW_DestroyRenderer(SDL_Renderer * renderer)
-{
- SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
-
- if (data) {
- SDL_free(data);
- }
- SDL_free(renderer);
-}
-
-/* vi: set ts=4 sw=4 expandtab: */
--- a/src/render/software/SDL_renderer_sw_c.h Sat Feb 05 11:54:46 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- SDL - Simple DirectMedia Layer
- Copyright (C) 1997-2010 Sam Lantinga
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- Sam Lantinga
- slouken@libsdl.org
-*/
-
-extern SDL_Renderer * SW_CreateRendererForSurface(SDL_Surface * surface);
-
-/* vi: set ts=4 sw=4 expandtab: */