Changed include directive to standard header.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "SDL_config.h"
23 #if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
26 #include "../../core/windows/SDL_windows.h"
28 #include "SDL_hints.h"
29 #include "SDL_loadso.h"
30 #include "SDL_syswm.h"
31 #include "../SDL_sysrender.h"
34 #if SDL_VIDEO_RENDER_D3D
35 #define D3D_DEBUG_INFO
40 typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK;
41 typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX;
42 typedef struct _D3DVECTOR D3DXVECTOR3, *LPD3DXVECTOR3;
44 DEFINE_GUID(IID_ID3DXMatrixStack,
45 0xc7885ba7, 0xf990, 0x4fe7, 0x92, 0x2d, 0x85, 0x15, 0xe4, 0x77, 0xdd, 0x85);
48 #define INTERFACE ID3DXMatrixStack
50 DECLARE_INTERFACE_(ID3DXMatrixStack, IUnknown)
52 STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
53 STDMETHOD_(ULONG,AddRef)(THIS) PURE;
54 STDMETHOD_(ULONG,Release)(THIS) PURE;
55 STDMETHOD(Pop)(THIS) PURE;
56 STDMETHOD(Push)(THIS) PURE;
57 STDMETHOD(LoadIdentity)(THIS) PURE;
58 STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
59 STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
60 STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE;
61 STDMETHOD(RotateAxis)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
62 STDMETHOD(RotateAxisLocal)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
63 STDMETHOD(RotateYawPitchRoll)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
64 STDMETHOD(RotateYawPitchRollLocal)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
65 STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
66 STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
67 STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE;
68 STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
69 STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE;
74 #if !defined(__cplusplus) || defined(CINTERFACE)
75 #define ID3DXMatrixStack_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
76 #define ID3DXMatrixStack_AddRef(p) (p)->lpVtbl->AddRef(p)
77 #define ID3DXMatrixStack_Release(p) (p)->lpVtbl->Release(p)
78 #define ID3DXMatrixStack_Pop(p) (p)->lpVtbl->Pop(p)
79 #define ID3DXMatrixStack_Push(p) (p)->lpVtbl->Push(p)
80 #define ID3DXMatrixStack_LoadIdentity(p) (p)->lpVtbl->LoadIdentity(p)
81 #define ID3DXMatrixStack_LoadMatrix(p,a) (p)->lpVtbl->LoadMatrix(p,a)
82 #define ID3DXMatrixStack_MultMatrix(p,a) (p)->lpVtbl->MultMatrix(p,a)
83 #define ID3DXMatrixStack_MultMatrixLocal(p,a) (p)->lpVtbl->MultMatrixLocal(p,a)
84 #define ID3DXMatrixStack_RotateAxis(p,a,b) (p)->lpVtbl->RotateAxis(p,a,b)
85 #define ID3DXMatrixStack_RotateAxisLocal(p,a,b) (p)->lpVtbl->RotateAxisLocal(p,a,b)
86 #define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c) (p)->lpVtbl->RotateYawPitchRoll(p,a,b,c)
87 #define ID3DXMatrixStack_RotateYawPitchRollLocal(p,a,b,c) (p)->lpVtbl->RotateYawPitchRollLocal(p,a,b,c)
88 #define ID3DXMatrixStack_Scale(p,a,b,c) (p)->lpVtbl->Scale(p,a,b,c)
89 #define ID3DXMatrixStack_ScaleLocal(p,a,b,c) (p)->lpVtbl->ScaleLocal(p,a,b,c)
90 #define ID3DXMatrixStack_Translate(p,a,b,c) (p)->lpVtbl->Translate(p,a,b,c)
91 #define ID3DXMatrixStack_TranslateLocal(p,a,b,c) (p)->lpVtbl->TranslateLocal(p,a,b,c)
92 #define ID3DXMatrixStack_GetTop(p) (p)->lpVtbl->GetTop(p)
94 #define ID3DXMatrixStack_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
95 #define ID3DXMatrixStack_AddRef(p) (p)->AddRef()
96 #define ID3DXMatrixStack_Release(p) (p)->Release()
97 #define ID3DXMatrixStack_Pop(p) (p)->Pop()
98 #define ID3DXMatrixStack_Push(p) (p)->Push()
99 #define ID3DXMatrixStack_LoadIdentity(p) (p)->LoadIdentity()
100 #define ID3DXMatrixStack_LoadMatrix(p,a) (p)->LoadMatrix(a)
101 #define ID3DXMatrixStack_MultMatrix(p,a) (p)->MultMatrix(a)
102 #define ID3DXMatrixStack_MultMatrixLocal(p,a) (p)->MultMatrixLocal(a)
103 #define ID3DXMatrixStack_RotateAxis(p,a,b) (p)->RotateAxis(a,b)
104 #define ID3DXMatrixStack_RotateAxisLocal(p,a,b) (p)->RotateAxisLocal(a,b)
105 #define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c) (p)->RotateYawPitchRollLocal(a,b,c)
106 #define ID3DXMatrixStack_Scale(p,a,b,c) (p)->Scale(a,b,c)
107 #define ID3DXMatrixStack_ScaleLocal(p,a,b,c) (p)->ScaleLocal(a,b,c)
108 #define ID3DXMatrixStack_Translate(p,a,b,c) (p)->Translate(a,b,c)
109 #define ID3DXMatrixStack_TranslateLocal(p,a,b,c) (p)->TranslateLocal(a,b,c)
110 #define ID3DXMatrixStack_GetTop(p) (p)->GetTop()
117 HRESULT WINAPI D3DXCreateMatrixStack(DWORD flags, LPD3DXMATRIXSTACK* ppstack);
123 #ifdef ASSEMBLE_SHADER
124 /**************************************************************************
127 * The buffer object is used by D3DX to return arbitrary size data.
130 * Returns a pointer to the beginning of the buffer.
133 * Returns the size of the buffer, in bytes.
134 **************************************************************************/
136 typedef interface ID3DXBuffer ID3DXBuffer;
137 typedef interface ID3DXBuffer *LPD3DXBUFFER;
139 /* {8BA5FB08-5195-40e2-AC58-0D989C3A0102} */
140 DEFINE_GUID(IID_ID3DXBuffer,
141 0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
144 #define INTERFACE ID3DXBuffer
146 typedef interface ID3DXBuffer {
147 const struct ID3DXBufferVtbl FAR* lpVtbl;
149 typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
150 const struct ID3DXBufferVtbl
153 STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
154 STDMETHOD_(ULONG, AddRef)(THIS) PURE;
155 STDMETHOD_(ULONG, Release)(THIS) PURE;
158 STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
159 STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
166 CONST LPVOID* pDefines,
169 LPD3DXBUFFER* ppShader,
170 LPD3DXBUFFER* ppErrorMsgs);
172 #endif /* ASSEMBLE_SHADER */
175 /* Direct3D renderer implementation */
177 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
178 static void D3D_WindowEvent(SDL_Renderer * renderer,
179 const SDL_WindowEvent *event);
180 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
181 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
182 const SDL_Rect * rect, const void *pixels,
184 static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
185 const SDL_Rect * rect, void **pixels, int *pitch);
186 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
187 static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
188 static int D3D_UpdateViewport(SDL_Renderer * renderer);
189 static int D3D_UpdateClipRect(SDL_Renderer * renderer);
190 static int D3D_RenderClear(SDL_Renderer * renderer);
191 static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
192 const SDL_FPoint * points, int count);
193 static int D3D_RenderDrawLines(SDL_Renderer * renderer,
194 const SDL_FPoint * points, int count);
195 static int D3D_RenderFillRects(SDL_Renderer * renderer,
196 const SDL_FRect * rects, int count);
197 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
198 const SDL_Rect * srcrect, const SDL_FRect * dstrect);
199 static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
200 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
201 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
202 static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
203 Uint32 format, void * pixels, int pitch);
204 static void D3D_RenderPresent(SDL_Renderer * renderer);
205 static void D3D_DestroyTexture(SDL_Renderer * renderer,
206 SDL_Texture * texture);
207 static void D3D_DestroyRenderer(SDL_Renderer * renderer);
210 SDL_RenderDriver D3D_RenderDriver = {
214 (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
216 {SDL_PIXELFORMAT_ARGB8888},
225 IDirect3DDevice9 *device;
227 D3DPRESENT_PARAMETERS pparams;
230 D3DTEXTUREFILTERTYPE scaleMode;
231 IDirect3DSurface9 *defaultRenderTarget;
232 IDirect3DSurface9 *currentRenderTarget;
234 ID3DXMatrixStack *matrixStack;
239 IDirect3DTexture9 *texture;
240 D3DTEXTUREFILTERTYPE scaleMode;
251 D3D_SetError(const char *prefix, HRESULT result)
256 case D3DERR_WRONGTEXTUREFORMAT:
257 error = "WRONGTEXTUREFORMAT";
259 case D3DERR_UNSUPPORTEDCOLOROPERATION:
260 error = "UNSUPPORTEDCOLOROPERATION";
262 case D3DERR_UNSUPPORTEDCOLORARG:
263 error = "UNSUPPORTEDCOLORARG";
265 case D3DERR_UNSUPPORTEDALPHAOPERATION:
266 error = "UNSUPPORTEDALPHAOPERATION";
268 case D3DERR_UNSUPPORTEDALPHAARG:
269 error = "UNSUPPORTEDALPHAARG";
271 case D3DERR_TOOMANYOPERATIONS:
272 error = "TOOMANYOPERATIONS";
274 case D3DERR_CONFLICTINGTEXTUREFILTER:
275 error = "CONFLICTINGTEXTUREFILTER";
277 case D3DERR_UNSUPPORTEDFACTORVALUE:
278 error = "UNSUPPORTEDFACTORVALUE";
280 case D3DERR_CONFLICTINGRENDERSTATE:
281 error = "CONFLICTINGRENDERSTATE";
283 case D3DERR_UNSUPPORTEDTEXTUREFILTER:
284 error = "UNSUPPORTEDTEXTUREFILTER";
286 case D3DERR_CONFLICTINGTEXTUREPALETTE:
287 error = "CONFLICTINGTEXTUREPALETTE";
289 case D3DERR_DRIVERINTERNALERROR:
290 error = "DRIVERINTERNALERROR";
292 case D3DERR_NOTFOUND:
295 case D3DERR_MOREDATA:
298 case D3DERR_DEVICELOST:
299 error = "DEVICELOST";
301 case D3DERR_DEVICENOTRESET:
302 error = "DEVICENOTRESET";
304 case D3DERR_NOTAVAILABLE:
305 error = "NOTAVAILABLE";
307 case D3DERR_OUTOFVIDEOMEMORY:
308 error = "OUTOFVIDEOMEMORY";
310 case D3DERR_INVALIDDEVICE:
311 error = "INVALIDDEVICE";
313 case D3DERR_INVALIDCALL:
314 error = "INVALIDCALL";
316 case D3DERR_DRIVERINVALIDCALL:
317 error = "DRIVERINVALIDCALL";
319 case D3DERR_WASSTILLDRAWING:
320 error = "WASSTILLDRAWING";
326 return SDL_SetError("%s: %s", prefix, error);
330 PixelFormatToD3DFMT(Uint32 format)
333 case SDL_PIXELFORMAT_RGB565:
334 return D3DFMT_R5G6B5;
335 case SDL_PIXELFORMAT_RGB888:
336 return D3DFMT_X8R8G8B8;
337 case SDL_PIXELFORMAT_ARGB8888:
338 return D3DFMT_A8R8G8B8;
340 return D3DFMT_UNKNOWN;
345 D3DFMTToPixelFormat(D3DFORMAT format)
349 return SDL_PIXELFORMAT_RGB565;
350 case D3DFMT_X8R8G8B8:
351 return SDL_PIXELFORMAT_RGB888;
352 case D3DFMT_A8R8G8B8:
353 return SDL_PIXELFORMAT_ARGB8888;
355 return SDL_PIXELFORMAT_UNKNOWN;
360 D3D_Reset(SDL_Renderer * renderer)
362 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
365 /* Release the default render target before reset */
366 if (data->defaultRenderTarget) {
367 IDirect3DSurface9_Release(data->defaultRenderTarget);
368 data->defaultRenderTarget = NULL;
371 result = IDirect3DDevice9_Reset(data->device, &data->pparams);
372 if (FAILED(result)) {
373 if (result == D3DERR_DEVICELOST) {
374 /* Don't worry about it, we'll reset later... */
377 return D3D_SetError("Reset()", result);
380 IDirect3DDevice9_SetVertexShader(data->device, NULL);
381 IDirect3DDevice9_SetFVF(data->device,
382 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
383 IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
385 IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
386 IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
387 data->scaleMode = D3DTEXF_FORCE_DWORD;
392 D3D_ActivateRenderer(SDL_Renderer * renderer)
394 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
397 if (data->updateSize) {
398 SDL_Window *window = renderer->window;
401 SDL_GetWindowSize(window, &w, &h);
402 data->pparams.BackBufferWidth = w;
403 data->pparams.BackBufferHeight = h;
404 if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
405 data->pparams.BackBufferFormat =
406 PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));
408 data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
410 if (D3D_Reset(renderer) < 0) {
413 D3D_UpdateViewport(renderer);
415 data->updateSize = SDL_FALSE;
417 if (data->beginScene) {
418 result = IDirect3DDevice9_BeginScene(data->device);
419 if (result == D3DERR_DEVICELOST) {
420 if (D3D_Reset(renderer) < 0) {
423 result = IDirect3DDevice9_BeginScene(data->device);
425 if (FAILED(result)) {
426 return D3D_SetError("BeginScene()", result);
428 data->beginScene = SDL_FALSE;
434 D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
436 SDL_Renderer *renderer;
437 D3D_RenderData *data;
438 SDL_SysWMinfo windowinfo;
440 D3DPRESENT_PARAMETERS pparams;
441 IDirect3DSwapChain9 *chain;
445 SDL_DisplayMode fullscreen_mode;
448 char d3dxDLLFile[50];
450 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
456 data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
463 data->d3dDLL = SDL_LoadObject("D3D9.DLL");
465 IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
468 (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL,
471 data->d3d = D3DCreate(D3D_SDK_VERSION);
474 SDL_UnloadObject(data->d3dDLL);
478 for (d3dxVersion=50;d3dxVersion>0;d3dxVersion--) {
480 SDL_snprintf(d3dxDLLFile, sizeof(d3dxDLLFile), "D3DX9_%02d.dll", d3dxVersion);
481 dllName = WIN_UTF8ToString(d3dxDLLFile);
482 data->d3dxDLL = (void *)LoadLibrary(dllName); /* not using SDL_LoadObject() as we want silently fail - no error message */
485 HRESULT (WINAPI *D3DXCreateMatrixStack) (DWORD Flags, LPD3DXMATRIXSTACK* ppStack);
486 D3DXCreateMatrixStack = (HRESULT (WINAPI *) (DWORD, LPD3DXMATRIXSTACK*)) SDL_LoadFunction(data->d3dxDLL, "D3DXCreateMatrixStack");
487 if (D3DXCreateMatrixStack) {
488 D3DXCreateMatrixStack(0, &data->matrixStack);
494 if (!data->matrixStack) {
495 if (data->d3dxDLL) SDL_UnloadObject(data->d3dxDLL);
501 if (!data->d3d || !data->matrixStack) {
504 SDL_SetError("Unable to create Direct3D interface");
508 renderer->WindowEvent = D3D_WindowEvent;
509 renderer->CreateTexture = D3D_CreateTexture;
510 renderer->UpdateTexture = D3D_UpdateTexture;
511 renderer->LockTexture = D3D_LockTexture;
512 renderer->UnlockTexture = D3D_UnlockTexture;
513 renderer->SetRenderTarget = D3D_SetRenderTarget;
514 renderer->UpdateViewport = D3D_UpdateViewport;
515 renderer->UpdateClipRect = D3D_UpdateClipRect;
516 renderer->RenderClear = D3D_RenderClear;
517 renderer->RenderDrawPoints = D3D_RenderDrawPoints;
518 renderer->RenderDrawLines = D3D_RenderDrawLines;
519 renderer->RenderFillRects = D3D_RenderFillRects;
520 renderer->RenderCopy = D3D_RenderCopy;
521 renderer->RenderCopyEx = D3D_RenderCopyEx;
522 renderer->RenderReadPixels = D3D_RenderReadPixels;
523 renderer->RenderPresent = D3D_RenderPresent;
524 renderer->DestroyTexture = D3D_DestroyTexture;
525 renderer->DestroyRenderer = D3D_DestroyRenderer;
526 renderer->info = D3D_RenderDriver.info;
527 renderer->driverdata = data;
529 renderer->info.flags = SDL_RENDERER_ACCELERATED;
531 SDL_VERSION(&windowinfo.version);
532 SDL_GetWindowWMInfo(window, &windowinfo);
534 window_flags = SDL_GetWindowFlags(window);
535 SDL_GetWindowSize(window, &w, &h);
536 SDL_GetWindowDisplayMode(window, &fullscreen_mode);
539 pparams.hDeviceWindow = windowinfo.info.win.window;
540 pparams.BackBufferWidth = w;
541 pparams.BackBufferHeight = h;
542 if (window_flags & SDL_WINDOW_FULLSCREEN) {
543 pparams.BackBufferFormat =
544 PixelFormatToD3DFMT(fullscreen_mode.format);
546 pparams.BackBufferFormat = D3DFMT_UNKNOWN;
548 pparams.BackBufferCount = 1;
549 pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
551 if (window_flags & SDL_WINDOW_FULLSCREEN) {
552 if ( ( window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP ) {
553 pparams.Windowed = TRUE;
554 pparams.FullScreen_RefreshRateInHz = 0;
556 pparams.Windowed = FALSE;
557 pparams.FullScreen_RefreshRateInHz =
558 fullscreen_mode.refresh_rate;
561 pparams.Windowed = TRUE;
562 pparams.FullScreen_RefreshRateInHz = 0;
564 if (flags & SDL_RENDERER_PRESENTVSYNC) {
565 pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
567 pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
570 /* FIXME: Which adapter? */
571 data->adapter = D3DADAPTER_DEFAULT;
572 IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
574 result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
576 pparams.hDeviceWindow,
577 D3DCREATE_FPU_PRESERVE | ((caps.
579 D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
580 D3DCREATE_HARDWARE_VERTEXPROCESSING :
581 D3DCREATE_SOFTWARE_VERTEXPROCESSING),
582 &pparams, &data->device);
583 if (FAILED(result)) {
584 D3D_DestroyRenderer(renderer);
585 D3D_SetError("CreateDevice()", result);
588 data->beginScene = SDL_TRUE;
589 data->scaleMode = D3DTEXF_FORCE_DWORD;
591 /* Get presentation parameters to fill info */
592 result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
593 if (FAILED(result)) {
594 D3D_DestroyRenderer(renderer);
595 D3D_SetError("GetSwapChain()", result);
598 result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
599 if (FAILED(result)) {
600 IDirect3DSwapChain9_Release(chain);
601 D3D_DestroyRenderer(renderer);
602 D3D_SetError("GetPresentParameters()", result);
605 IDirect3DSwapChain9_Release(chain);
606 if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
607 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
609 data->pparams = pparams;
611 IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
612 renderer->info.max_texture_width = caps.MaxTextureWidth;
613 renderer->info.max_texture_height = caps.MaxTextureHeight;
614 if (caps.NumSimultaneousRTs >= 2) {
615 renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
618 /* Set up parameters for rendering */
619 IDirect3DDevice9_SetVertexShader(data->device, NULL);
620 IDirect3DDevice9_SetFVF(data->device,
621 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
622 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
623 IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
625 IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
626 /* Enable color modulation by diffuse color */
627 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
629 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
631 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
633 /* Enable alpha modulation by diffuse alpha */
634 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
636 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
638 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
640 /* Disable second texture stage, since we're done */
641 IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
643 IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
646 /* Store the default render target */
647 IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget );
648 data->currentRenderTarget = NULL;
650 /* Set an identity world and view matrix */
651 matrix.m[0][0] = 1.0f;
652 matrix.m[0][1] = 0.0f;
653 matrix.m[0][2] = 0.0f;
654 matrix.m[0][3] = 0.0f;
655 matrix.m[1][0] = 0.0f;
656 matrix.m[1][1] = 1.0f;
657 matrix.m[1][2] = 0.0f;
658 matrix.m[1][3] = 0.0f;
659 matrix.m[2][0] = 0.0f;
660 matrix.m[2][1] = 0.0f;
661 matrix.m[2][2] = 1.0f;
662 matrix.m[2][3] = 0.0f;
663 matrix.m[3][0] = 0.0f;
664 matrix.m[3][1] = 0.0f;
665 matrix.m[3][2] = 0.0f;
666 matrix.m[3][3] = 1.0f;
667 IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix);
668 IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix);
674 D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
676 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
678 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
679 data->updateSize = SDL_TRUE;
683 static D3DTEXTUREFILTERTYPE
684 GetScaleQuality(void)
686 const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
688 if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
689 return D3DTEXF_POINT;
690 } else if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) {
691 return D3DTEXF_LINEAR;
693 return D3DTEXF_ANISOTROPIC;
698 D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
700 D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
701 D3D_TextureData *data;
706 data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
708 return SDL_OutOfMemory();
710 data->scaleMode = GetScaleQuality();
712 texture->driverdata = data;
714 #ifdef USE_DYNAMIC_TEXTURE
715 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
716 pool = D3DPOOL_DEFAULT;
717 usage = D3DUSAGE_DYNAMIC;
720 if (texture->access == SDL_TEXTUREACCESS_TARGET) {
721 /* D3DPOOL_MANAGED does not work with D3DUSAGE_RENDERTARGET */
722 pool = D3DPOOL_DEFAULT;
723 usage = D3DUSAGE_RENDERTARGET;
725 pool = D3DPOOL_MANAGED;
730 IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
731 texture->h, 1, usage,
732 PixelFormatToD3DFMT(texture->format),
733 pool, &data->texture, NULL);
734 if (FAILED(result)) {
735 return D3D_SetError("CreateTexture()", result);
742 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
743 const SDL_Rect * rect, const void *pixels, int pitch)
745 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
747 D3DLOCKED_RECT locked;
753 #ifdef USE_DYNAMIC_TEXTURE
754 if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
755 rect->x == 0 && rect->y == 0 &&
756 rect->w == texture->w && rect->h == texture->h) {
757 result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
761 d3drect.left = rect->x;
762 d3drect.right = rect->x + rect->w;
763 d3drect.top = rect->y;
764 d3drect.bottom = rect->y + rect->h;
765 result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
768 if (FAILED(result)) {
769 return D3D_SetError("LockRect()", result);
774 length = rect->w * SDL_BYTESPERPIXEL(texture->format);
775 if (length == pitch && length == locked.Pitch) {
776 SDL_memcpy(dst, src, length*rect->h);
778 for (row = 0; row < rect->h; ++row) {
779 SDL_memcpy(dst, src, length);
784 IDirect3DTexture9_UnlockRect(data->texture, 0);
790 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
791 const SDL_Rect * rect, void **pixels, int *pitch)
793 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
795 D3DLOCKED_RECT locked;
798 d3drect.left = rect->x;
799 d3drect.right = rect->x + rect->w;
800 d3drect.top = rect->y;
801 d3drect.bottom = rect->y + rect->h;
803 result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
804 if (FAILED(result)) {
805 return D3D_SetError("LockRect()", result);
807 *pixels = locked.pBits;
808 *pitch = locked.Pitch;
813 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
815 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
817 IDirect3DTexture9_UnlockRect(data->texture, 0);
821 D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
823 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
824 D3D_TextureData *texturedata;
827 D3D_ActivateRenderer(renderer);
829 /* Release the previous render target if it wasn't the default one */
830 if (data->currentRenderTarget != NULL) {
831 IDirect3DSurface9_Release(data->currentRenderTarget);
832 data->currentRenderTarget = NULL;
835 if (texture == NULL) {
836 IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
840 texturedata = (D3D_TextureData *) texture->driverdata;
841 result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture, 0, &data->currentRenderTarget);
843 return D3D_SetError("GetSurfaceLevel()", result);
845 result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget);
847 return D3D_SetError("SetRenderTarget()", result);
854 D3D_UpdateViewport(SDL_Renderer * renderer)
856 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
857 D3DVIEWPORT9 viewport;
860 /* Set the viewport */
861 viewport.X = renderer->viewport.x;
862 viewport.Y = renderer->viewport.y;
863 viewport.Width = renderer->viewport.w;
864 viewport.Height = renderer->viewport.h;
865 viewport.MinZ = 0.0f;
866 viewport.MaxZ = 1.0f;
867 IDirect3DDevice9_SetViewport(data->device, &viewport);
869 /* Set an orthographic projection matrix */
870 if (renderer->viewport.w && renderer->viewport.h) {
871 matrix.m[0][0] = 2.0f / renderer->viewport.w;
872 matrix.m[0][1] = 0.0f;
873 matrix.m[0][2] = 0.0f;
874 matrix.m[0][3] = 0.0f;
875 matrix.m[1][0] = 0.0f;
876 matrix.m[1][1] = -2.0f / renderer->viewport.h;
877 matrix.m[1][2] = 0.0f;
878 matrix.m[1][3] = 0.0f;
879 matrix.m[2][0] = 0.0f;
880 matrix.m[2][1] = 0.0f;
881 matrix.m[2][2] = 1.0f;
882 matrix.m[2][3] = 0.0f;
883 matrix.m[3][0] = -1.0f;
884 matrix.m[3][1] = 1.0f;
885 matrix.m[3][2] = 0.0f;
886 matrix.m[3][3] = 1.0f;
887 IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
894 D3D_UpdateClipRect(SDL_Renderer * renderer)
896 const SDL_Rect *rect = &renderer->clip_rect;
897 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
901 if (!SDL_RectEmpty(rect)) {
902 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
905 r.right = rect->w + rect->w;
906 r.bottom = rect->y + rect->h;
908 result = IDirect3DDevice9_SetScissorRect(data->device, &r);
909 if (result != D3D_OK) {
910 D3D_SetError("SetScissor()", result);
914 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
920 D3D_RenderClear(SDL_Renderer * renderer)
922 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
926 if (D3D_ActivateRenderer(renderer) < 0) {
930 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
932 /* Don't reset the viewport if we don't have to! */
933 if (!renderer->viewport.x && !renderer->viewport.y &&
934 renderer->viewport.w == data->pparams.BackBufferWidth &&
935 renderer->viewport.h == data->pparams.BackBufferHeight) {
936 result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
938 D3DVIEWPORT9 viewport;
940 /* Clear is defined to clear the entire render target */
943 viewport.Width = data->pparams.BackBufferWidth;
944 viewport.Height = data->pparams.BackBufferHeight;
945 viewport.MinZ = 0.0f;
946 viewport.MaxZ = 1.0f;
947 IDirect3DDevice9_SetViewport(data->device, &viewport);
949 result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
951 /* Reset the viewport */
952 viewport.X = renderer->viewport.x;
953 viewport.Y = renderer->viewport.y;
954 viewport.Width = renderer->viewport.w;
955 viewport.Height = renderer->viewport.h;
956 viewport.MinZ = 0.0f;
957 viewport.MaxZ = 1.0f;
958 IDirect3DDevice9_SetViewport(data->device, &viewport);
961 if (FAILED(result)) {
962 return D3D_SetError("Clear()", result);
968 D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
971 case SDL_BLENDMODE_NONE:
972 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
975 case SDL_BLENDMODE_BLEND:
976 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
978 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
980 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
981 D3DBLEND_INVSRCALPHA);
983 case SDL_BLENDMODE_ADD:
984 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
986 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
988 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
991 case SDL_BLENDMODE_MOD:
992 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
994 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
996 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
1003 D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
1006 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1012 if (D3D_ActivateRenderer(renderer) < 0) {
1016 D3D_SetBlendMode(data, renderer->blendMode);
1019 IDirect3DDevice9_SetTexture(data->device, 0,
1020 (IDirect3DBaseTexture9 *) 0);
1021 if (FAILED(result)) {
1022 return D3D_SetError("SetTexture()", result);
1025 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1027 vertices = SDL_stack_alloc(Vertex, count);
1028 for (i = 0; i < count; ++i) {
1029 vertices[i].x = points[i].x;
1030 vertices[i].y = points[i].y;
1031 vertices[i].z = 0.0f;
1032 vertices[i].color = color;
1033 vertices[i].u = 0.0f;
1034 vertices[i].v = 0.0f;
1037 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
1038 vertices, sizeof(*vertices));
1039 SDL_stack_free(vertices);
1040 if (FAILED(result)) {
1041 return D3D_SetError("DrawPrimitiveUP()", result);
1047 D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
1050 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1056 if (D3D_ActivateRenderer(renderer) < 0) {
1060 D3D_SetBlendMode(data, renderer->blendMode);
1063 IDirect3DDevice9_SetTexture(data->device, 0,
1064 (IDirect3DBaseTexture9 *) 0);
1065 if (FAILED(result)) {
1066 return D3D_SetError("SetTexture()", result);
1069 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1071 vertices = SDL_stack_alloc(Vertex, count);
1072 for (i = 0; i < count; ++i) {
1073 vertices[i].x = points[i].x;
1074 vertices[i].y = points[i].y;
1075 vertices[i].z = 0.0f;
1076 vertices[i].color = color;
1077 vertices[i].u = 0.0f;
1078 vertices[i].v = 0.0f;
1081 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
1082 vertices, sizeof(*vertices));
1084 /* DirectX 9 has the same line rasterization semantics as GDI,
1085 so we need to close the endpoint of the line */
1087 points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1088 vertices[0].x = points[count-1].x;
1089 vertices[0].y = points[count-1].y;
1090 result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
1093 SDL_stack_free(vertices);
1094 if (FAILED(result)) {
1095 return D3D_SetError("DrawPrimitiveUP()", result);
1101 D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
1104 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1107 float minx, miny, maxx, maxy;
1111 if (D3D_ActivateRenderer(renderer) < 0) {
1115 D3D_SetBlendMode(data, renderer->blendMode);
1118 IDirect3DDevice9_SetTexture(data->device, 0,
1119 (IDirect3DBaseTexture9 *) 0);
1120 if (FAILED(result)) {
1121 return D3D_SetError("SetTexture()", result);
1124 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1126 for (i = 0; i < count; ++i) {
1127 const SDL_FRect *rect = &rects[i];
1131 maxx = rect->x + rect->w;
1132 maxy = rect->y + rect->h;
1134 vertices[0].x = minx;
1135 vertices[0].y = miny;
1136 vertices[0].z = 0.0f;
1137 vertices[0].color = color;
1138 vertices[0].u = 0.0f;
1139 vertices[0].v = 0.0f;
1141 vertices[1].x = maxx;
1142 vertices[1].y = miny;
1143 vertices[1].z = 0.0f;
1144 vertices[1].color = color;
1145 vertices[1].u = 0.0f;
1146 vertices[1].v = 0.0f;
1148 vertices[2].x = maxx;
1149 vertices[2].y = maxy;
1150 vertices[2].z = 0.0f;
1151 vertices[2].color = color;
1152 vertices[2].u = 0.0f;
1153 vertices[2].v = 0.0f;
1155 vertices[3].x = minx;
1156 vertices[3].y = maxy;
1157 vertices[3].z = 0.0f;
1158 vertices[3].color = color;
1159 vertices[3].u = 0.0f;
1160 vertices[3].v = 0.0f;
1163 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
1164 2, vertices, sizeof(*vertices));
1165 if (FAILED(result)) {
1166 return D3D_SetError("DrawPrimitiveUP()", result);
1173 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1174 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1176 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1177 D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
1178 LPDIRECT3DPIXELSHADER9 shader = NULL;
1179 float minx, miny, maxx, maxy;
1180 float minu, maxu, minv, maxv;
1185 if (D3D_ActivateRenderer(renderer) < 0) {
1189 minx = dstrect->x - 0.5f;
1190 miny = dstrect->y - 0.5f;
1191 maxx = dstrect->x + dstrect->w - 0.5f;
1192 maxy = dstrect->y + dstrect->h - 0.5f;
1194 minu = (float) srcrect->x / texture->w;
1195 maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1196 minv = (float) srcrect->y / texture->h;
1197 maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1199 color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1201 vertices[0].x = minx;
1202 vertices[0].y = miny;
1203 vertices[0].z = 0.0f;
1204 vertices[0].color = color;
1205 vertices[0].u = minu;
1206 vertices[0].v = minv;
1208 vertices[1].x = maxx;
1209 vertices[1].y = miny;
1210 vertices[1].z = 0.0f;
1211 vertices[1].color = color;
1212 vertices[1].u = maxu;
1213 vertices[1].v = minv;
1215 vertices[2].x = maxx;
1216 vertices[2].y = maxy;
1217 vertices[2].z = 0.0f;
1218 vertices[2].color = color;
1219 vertices[2].u = maxu;
1220 vertices[2].v = maxv;
1222 vertices[3].x = minx;
1223 vertices[3].y = maxy;
1224 vertices[3].z = 0.0f;
1225 vertices[3].color = color;
1226 vertices[3].u = minu;
1227 vertices[3].v = maxv;
1229 D3D_SetBlendMode(data, texture->blendMode);
1231 if (texturedata->scaleMode != data->scaleMode) {
1232 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
1233 texturedata->scaleMode);
1234 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
1235 texturedata->scaleMode);
1236 data->scaleMode = texturedata->scaleMode;
1240 IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
1241 texturedata->texture);
1242 if (FAILED(result)) {
1243 return D3D_SetError("SetTexture()", result);
1246 result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1247 if (FAILED(result)) {
1248 return D3D_SetError("SetShader()", result);
1252 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
1253 vertices, sizeof(*vertices));
1254 if (FAILED(result)) {
1255 return D3D_SetError("DrawPrimitiveUP()", result);
1258 result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
1259 if (FAILED(result)) {
1260 return D3D_SetError("SetShader()", result);
1268 D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1269 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1270 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
1272 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1273 D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
1274 LPDIRECT3DPIXELSHADER9 shader = NULL;
1275 float minx, miny, maxx, maxy;
1276 float minu, maxu, minv, maxv;
1277 float centerx, centery;
1282 if (D3D_ActivateRenderer(renderer) < 0) {
1286 centerx = center->x;
1287 centery = center->y;
1289 if (flip & SDL_FLIP_HORIZONTAL) {
1290 minx = dstrect->w - centerx - 0.5f;
1291 maxx = -centerx - 0.5f;
1294 minx = -centerx - 0.5f;
1295 maxx = dstrect->w - centerx - 0.5f;
1298 if (flip & SDL_FLIP_VERTICAL) {
1299 miny = dstrect->h - centery - 0.5f;
1300 maxy = -centery - 0.5f;
1303 miny = -centery - 0.5f;
1304 maxy = dstrect->h - centery - 0.5f;
1307 minu = (float) srcrect->x / texture->w;
1308 maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1309 minv = (float) srcrect->y / texture->h;
1310 maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1312 color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1314 vertices[0].x = minx;
1315 vertices[0].y = miny;
1316 vertices[0].z = 0.0f;
1317 vertices[0].color = color;
1318 vertices[0].u = minu;
1319 vertices[0].v = minv;
1321 vertices[1].x = maxx;
1322 vertices[1].y = miny;
1323 vertices[1].z = 0.0f;
1324 vertices[1].color = color;
1325 vertices[1].u = maxu;
1326 vertices[1].v = minv;
1328 vertices[2].x = maxx;
1329 vertices[2].y = maxy;
1330 vertices[2].z = 0.0f;
1331 vertices[2].color = color;
1332 vertices[2].u = maxu;
1333 vertices[2].v = maxv;
1335 vertices[3].x = minx;
1336 vertices[3].y = maxy;
1337 vertices[3].z = 0.0f;
1338 vertices[3].color = color;
1339 vertices[3].u = minu;
1340 vertices[3].v = maxv;
1342 D3D_SetBlendMode(data, texture->blendMode);
1344 /* Rotate and translate */
1345 ID3DXMatrixStack_Push(data->matrixStack);
1346 ID3DXMatrixStack_LoadIdentity(data->matrixStack);
1347 ID3DXMatrixStack_RotateYawPitchRoll(data->matrixStack, 0.0, 0.0, (float)(M_PI * (float) angle / 180.0f));
1348 ID3DXMatrixStack_Translate(data->matrixStack, (float)dstrect->x + centerx, (float)dstrect->y + centery, (float)0.0);
1349 IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
1351 if (texturedata->scaleMode != data->scaleMode) {
1352 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
1353 texturedata->scaleMode);
1354 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
1355 texturedata->scaleMode);
1356 data->scaleMode = texturedata->scaleMode;
1360 IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
1361 texturedata->texture);
1362 if (FAILED(result)) {
1363 return D3D_SetError("SetTexture()", result);
1366 result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1367 if (FAILED(result)) {
1368 return D3D_SetError("SetShader()", result);
1372 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
1373 vertices, sizeof(*vertices));
1374 if (FAILED(result)) {
1375 return D3D_SetError("DrawPrimitiveUP()", result);
1378 result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
1379 if (FAILED(result)) {
1380 return D3D_SetError("SetShader()", result);
1383 ID3DXMatrixStack_Pop(data->matrixStack);
1384 ID3DXMatrixStack_Push(data->matrixStack);
1385 ID3DXMatrixStack_LoadIdentity(data->matrixStack);
1386 IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
1387 ID3DXMatrixStack_Pop(data->matrixStack);
1392 D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1393 Uint32 format, void * pixels, int pitch)
1395 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1396 D3DSURFACE_DESC desc;
1397 LPDIRECT3DSURFACE9 backBuffer;
1398 LPDIRECT3DSURFACE9 surface;
1400 D3DLOCKED_RECT locked;
1403 result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
1404 if (FAILED(result)) {
1405 return D3D_SetError("GetBackBuffer()", result);
1408 result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
1409 if (FAILED(result)) {
1410 IDirect3DSurface9_Release(backBuffer);
1411 return D3D_SetError("GetDesc()", result);
1414 result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
1415 if (FAILED(result)) {
1416 IDirect3DSurface9_Release(backBuffer);
1417 return D3D_SetError("CreateOffscreenPlainSurface()", result);
1420 result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
1421 if (FAILED(result)) {
1422 IDirect3DSurface9_Release(surface);
1423 IDirect3DSurface9_Release(backBuffer);
1424 return D3D_SetError("GetRenderTargetData()", result);
1427 d3drect.left = rect->x;
1428 d3drect.right = rect->x + rect->w;
1429 d3drect.top = rect->y;
1430 d3drect.bottom = rect->y + rect->h;
1432 result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
1433 if (FAILED(result)) {
1434 IDirect3DSurface9_Release(surface);
1435 IDirect3DSurface9_Release(backBuffer);
1436 return D3D_SetError("LockRect()", result);
1439 SDL_ConvertPixels(rect->w, rect->h,
1440 D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
1441 format, pixels, pitch);
1443 IDirect3DSurface9_UnlockRect(surface);
1445 IDirect3DSurface9_Release(surface);
1446 IDirect3DSurface9_Release(backBuffer);
1452 D3D_RenderPresent(SDL_Renderer * renderer)
1454 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1457 if (!data->beginScene) {
1458 IDirect3DDevice9_EndScene(data->device);
1459 data->beginScene = SDL_TRUE;
1462 result = IDirect3DDevice9_TestCooperativeLevel(data->device);
1463 if (result == D3DERR_DEVICELOST) {
1464 /* We'll reset later */
1467 if (result == D3DERR_DEVICENOTRESET) {
1468 D3D_Reset(renderer);
1470 result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
1471 if (FAILED(result)) {
1472 D3D_SetError("Present()", result);
1477 D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1479 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1484 if (data->texture) {
1485 IDirect3DTexture9_Release(data->texture);
1488 texture->driverdata = NULL;
1492 D3D_DestroyRenderer(SDL_Renderer * renderer)
1494 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1497 /* Release the render target */
1498 if (data->defaultRenderTarget) {
1499 IDirect3DSurface9_Release(data->defaultRenderTarget);
1500 data->defaultRenderTarget = NULL;
1502 if (data->currentRenderTarget != NULL) {
1503 IDirect3DSurface9_Release(data->currentRenderTarget);
1504 data->currentRenderTarget = NULL;
1508 IDirect3DDevice9_Release(data->device);
1511 IDirect3D9_Release(data->d3d);
1512 ID3DXMatrixStack_Release(data->matrixStack);
1513 SDL_UnloadObject(data->d3dDLL);
1520 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
1522 /* vi: set ts=4 sw=4 expandtab: */