zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_render_d3d.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
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.
8 
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:
12 
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.
20 */
21 #include "SDL_config.h"
22 
23 #if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
24 
25 
26 #include "../../core/windows/SDL_windows.h"
27 
28 #include "SDL_hints.h"
29 #include "SDL_loadso.h"
30 #include "SDL_syswm.h"
31 #include "SDL_system.h"
32 #include "../SDL_sysrender.h"
33 #include "../../video/windows/SDL_windowsvideo.h"
34 
35 #if SDL_VIDEO_RENDER_D3D
36 #define D3D_DEBUG_INFO
37 #include <d3d9.h>
38 #endif
39 
40 
41 typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK;
42 typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX;
43 typedef struct _D3DVECTOR D3DXVECTOR3, *LPD3DXVECTOR3;
44 
45 DEFINE_GUID(IID_ID3DXMatrixStack,
46 0xc7885ba7, 0xf990, 0x4fe7, 0x92, 0x2d, 0x85, 0x15, 0xe4, 0x77, 0xdd, 0x85);
47 
48 #undef INTERFACE
49 #define INTERFACE ID3DXMatrixStack
50 
52 {
53  STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
54  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
55  STDMETHOD_(ULONG,Release)(THIS) PURE;
56  STDMETHOD(Pop)(THIS) PURE;
57  STDMETHOD(Push)(THIS) PURE;
58  STDMETHOD(LoadIdentity)(THIS) PURE;
59  STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
60  STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
61  STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE;
62  STDMETHOD(RotateAxis)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
63  STDMETHOD(RotateAxisLocal)(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
64  STDMETHOD(RotateYawPitchRoll)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
65  STDMETHOD(RotateYawPitchRollLocal)(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
66  STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
67  STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
68  STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE;
69  STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
70  STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE;
71 };
72 
73 #undef INTERFACE
74 
75 #if !defined(__cplusplus) || defined(CINTERFACE)
76 #define ID3DXMatrixStack_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
77 #define ID3DXMatrixStack_AddRef(p) (p)->lpVtbl->AddRef(p)
78 #define ID3DXMatrixStack_Release(p) (p)->lpVtbl->Release(p)
79 #define ID3DXMatrixStack_Pop(p) (p)->lpVtbl->Pop(p)
80 #define ID3DXMatrixStack_Push(p) (p)->lpVtbl->Push(p)
81 #define ID3DXMatrixStack_LoadIdentity(p) (p)->lpVtbl->LoadIdentity(p)
82 #define ID3DXMatrixStack_LoadMatrix(p,a) (p)->lpVtbl->LoadMatrix(p,a)
83 #define ID3DXMatrixStack_MultMatrix(p,a) (p)->lpVtbl->MultMatrix(p,a)
84 #define ID3DXMatrixStack_MultMatrixLocal(p,a) (p)->lpVtbl->MultMatrixLocal(p,a)
85 #define ID3DXMatrixStack_RotateAxis(p,a,b) (p)->lpVtbl->RotateAxis(p,a,b)
86 #define ID3DXMatrixStack_RotateAxisLocal(p,a,b) (p)->lpVtbl->RotateAxisLocal(p,a,b)
87 #define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c) (p)->lpVtbl->RotateYawPitchRoll(p,a,b,c)
88 #define ID3DXMatrixStack_RotateYawPitchRollLocal(p,a,b,c) (p)->lpVtbl->RotateYawPitchRollLocal(p,a,b,c)
89 #define ID3DXMatrixStack_Scale(p,a,b,c) (p)->lpVtbl->Scale(p,a,b,c)
90 #define ID3DXMatrixStack_ScaleLocal(p,a,b,c) (p)->lpVtbl->ScaleLocal(p,a,b,c)
91 #define ID3DXMatrixStack_Translate(p,a,b,c) (p)->lpVtbl->Translate(p,a,b,c)
92 #define ID3DXMatrixStack_TranslateLocal(p,a,b,c) (p)->lpVtbl->TranslateLocal(p,a,b,c)
93 #define ID3DXMatrixStack_GetTop(p) (p)->lpVtbl->GetTop(p)
94 #else
95 #define ID3DXMatrixStack_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
96 #define ID3DXMatrixStack_AddRef(p) (p)->AddRef()
97 #define ID3DXMatrixStack_Release(p) (p)->Release()
98 #define ID3DXMatrixStack_Pop(p) (p)->Pop()
99 #define ID3DXMatrixStack_Push(p) (p)->Push()
100 #define ID3DXMatrixStack_LoadIdentity(p) (p)->LoadIdentity()
101 #define ID3DXMatrixStack_LoadMatrix(p,a) (p)->LoadMatrix(a)
102 #define ID3DXMatrixStack_MultMatrix(p,a) (p)->MultMatrix(a)
103 #define ID3DXMatrixStack_MultMatrixLocal(p,a) (p)->MultMatrixLocal(a)
104 #define ID3DXMatrixStack_RotateAxis(p,a,b) (p)->RotateAxis(a,b)
105 #define ID3DXMatrixStack_RotateAxisLocal(p,a,b) (p)->RotateAxisLocal(a,b)
106 #define ID3DXMatrixStack_RotateYawPitchRoll(p,a,b,c) (p)->RotateYawPitchRollLocal(a,b,c)
107 #define ID3DXMatrixStack_Scale(p,a,b,c) (p)->Scale(a,b,c)
108 #define ID3DXMatrixStack_ScaleLocal(p,a,b,c) (p)->ScaleLocal(a,b,c)
109 #define ID3DXMatrixStack_Translate(p,a,b,c) (p)->Translate(a,b,c)
110 #define ID3DXMatrixStack_TranslateLocal(p,a,b,c) (p)->TranslateLocal(a,b,c)
111 #define ID3DXMatrixStack_GetTop(p) (p)->GetTop()
112 #endif
113 
114 #ifdef __cplusplus
115 extern "C" {
116 #endif
117 
119 
120 #ifdef __cplusplus
121 }
122 #endif
123 
124 #ifdef ASSEMBLE_SHADER
125 /**************************************************************************
126  * ID3DXBuffer:
127  * ------------
128  * The buffer object is used by D3DX to return arbitrary size data.
129  *
130  * GetBufferPointer -
131  * Returns a pointer to the beginning of the buffer.
132  *
133  * GetBufferSize -
134  * Returns the size of the buffer, in bytes.
135  **************************************************************************/
136 
137 typedef interface ID3DXBuffer ID3DXBuffer;
138 typedef interface ID3DXBuffer *LPD3DXBUFFER;
139 
140 /* {8BA5FB08-5195-40e2-AC58-0D989C3A0102} */
141 DEFINE_GUID(IID_ID3DXBuffer,
142 0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
143 
144 #undef INTERFACE
145 #define INTERFACE ID3DXBuffer
146 
147 typedef interface ID3DXBuffer {
148  const struct ID3DXBufferVtbl FAR* lpVtbl;
149 } ID3DXBuffer;
150 typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
151 const struct ID3DXBufferVtbl
152 {
153  /* IUnknown */
154  STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
155  STDMETHOD_(ULONG, AddRef)(THIS) PURE;
156  STDMETHOD_(ULONG, Release)(THIS) PURE;
157 
158  /* ID3DXBuffer */
159  STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
160  STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
161 };
162 
163 HRESULT WINAPI
165  LPCSTR pSrcData,
166  UINT SrcDataLen,
167  CONST LPVOID* pDefines,
168  LPVOID pInclude,
169  DWORD Flags,
170  LPD3DXBUFFER* ppShader,
171  LPD3DXBUFFER* ppErrorMsgs);
172 
173 static void PrintShaderData(LPDWORD shader_data, DWORD shader_size)
174 {
175  OutputDebugStringA("const DWORD shader_data[] = {\n\t");
176  {
177  SDL_bool newline = SDL_FALSE;
178  unsigned i;
179  for (i = 0; i < shader_size / sizeof(DWORD); ++i) {
180  char dword[11];
181  if (i > 0) {
182  if ((i%6) == 0) {
183  newline = SDL_TRUE;
184  }
185  if (newline) {
186  OutputDebugStringA(",\n ");
187  newline = SDL_FALSE;
188  } else {
189  OutputDebugStringA(", ");
190  }
191  }
192  SDL_snprintf(dword, sizeof(dword), "0x%8.8x", shader_data[i]);
193  OutputDebugStringA(dword);
194  }
195  OutputDebugStringA("\n};\n");
196  }
197 }
198 
199 #endif /* ASSEMBLE_SHADER */
200 
201 
202 /* Direct3D renderer implementation */
203 
204 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
205 static void D3D_WindowEvent(SDL_Renderer * renderer,
206  const SDL_WindowEvent *event);
207 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
208 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
209  const SDL_Rect * rect, const void *pixels,
210  int pitch);
211 static int D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
212  const SDL_Rect * rect,
213  const Uint8 *Yplane, int Ypitch,
214  const Uint8 *Uplane, int Upitch,
215  const Uint8 *Vplane, int Vpitch);
216 static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
217  const SDL_Rect * rect, void **pixels, int *pitch);
218 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
219 static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
220 static int D3D_UpdateViewport(SDL_Renderer * renderer);
221 static int D3D_UpdateClipRect(SDL_Renderer * renderer);
222 static int D3D_RenderClear(SDL_Renderer * renderer);
223 static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
224  const SDL_FPoint * points, int count);
225 static int D3D_RenderDrawLines(SDL_Renderer * renderer,
226  const SDL_FPoint * points, int count);
227 static int D3D_RenderFillRects(SDL_Renderer * renderer,
228  const SDL_FRect * rects, int count);
229 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
230  const SDL_Rect * srcrect, const SDL_FRect * dstrect);
231 static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
232  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
233  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
234 static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
235  Uint32 format, void * pixels, int pitch);
236 static void D3D_RenderPresent(SDL_Renderer * renderer);
237 static void D3D_DestroyTexture(SDL_Renderer * renderer,
238  SDL_Texture * texture);
239 static void D3D_DestroyRenderer(SDL_Renderer * renderer);
240 
241 
242 SDL_RenderDriver D3D_RenderDriver = {
243  D3D_CreateRenderer,
244  {
245  "direct3d",
247  1,
249  0,
250  0}
251 };
252 
253 typedef struct
254 {
255  void* d3dDLL;
256  IDirect3D9 *d3d;
257  IDirect3DDevice9 *device;
258  UINT adapter;
259  D3DPRESENT_PARAMETERS pparams;
260  SDL_bool updateSize;
261  SDL_bool beginScene;
262  SDL_bool enableSeparateAlphaBlend;
263  D3DTEXTUREFILTERTYPE scaleMode[8];
264  IDirect3DSurface9 *defaultRenderTarget;
265  IDirect3DSurface9 *currentRenderTarget;
266  void* d3dxDLL;
267  ID3DXMatrixStack *matrixStack;
268  LPDIRECT3DPIXELSHADER9 ps_yuv;
269 } D3D_RenderData;
270 
271 typedef struct
272 {
274  D3DTEXTUREFILTERTYPE scaleMode;
275 
276  /* YV12 texture support */
277  SDL_bool yuv;
278  IDirect3DTexture9 *utexture;
279  IDirect3DTexture9 *vtexture;
280  Uint8 *pixels;
281  int pitch;
282  SDL_Rect locked_rect;
283 } D3D_TextureData;
284 
285 typedef struct
286 {
287  float x, y, z;
288  DWORD color;
289  float u, v;
290 } Vertex;
291 
292 static int
293 D3D_SetError(const char *prefix, HRESULT result)
294 {
295  const char *error;
296 
297  switch (result) {
299  error = "WRONGTEXTUREFORMAT";
300  break;
302  error = "UNSUPPORTEDCOLOROPERATION";
303  break;
305  error = "UNSUPPORTEDCOLORARG";
306  break;
308  error = "UNSUPPORTEDALPHAOPERATION";
309  break;
311  error = "UNSUPPORTEDALPHAARG";
312  break;
314  error = "TOOMANYOPERATIONS";
315  break;
317  error = "CONFLICTINGTEXTUREFILTER";
318  break;
320  error = "UNSUPPORTEDFACTORVALUE";
321  break;
323  error = "CONFLICTINGRENDERSTATE";
324  break;
326  error = "UNSUPPORTEDTEXTUREFILTER";
327  break;
329  error = "CONFLICTINGTEXTUREPALETTE";
330  break;
332  error = "DRIVERINTERNALERROR";
333  break;
334  case D3DERR_NOTFOUND:
335  error = "NOTFOUND";
336  break;
337  case D3DERR_MOREDATA:
338  error = "MOREDATA";
339  break;
340  case D3DERR_DEVICELOST:
341  error = "DEVICELOST";
342  break;
344  error = "DEVICENOTRESET";
345  break;
346  case D3DERR_NOTAVAILABLE:
347  error = "NOTAVAILABLE";
348  break;
350  error = "OUTOFVIDEOMEMORY";
351  break;
353  error = "INVALIDDEVICE";
354  break;
355  case D3DERR_INVALIDCALL:
356  error = "INVALIDCALL";
357  break;
359  error = "DRIVERINVALIDCALL";
360  break;
362  error = "WASSTILLDRAWING";
363  break;
364  default:
365  error = "UNKNOWN";
366  break;
367  }
368  return SDL_SetError("%s: %s", prefix, error);
369 }
370 
371 static D3DFORMAT
372 PixelFormatToD3DFMT(Uint32 format)
373 {
374  switch (format) {
376  return D3DFMT_R5G6B5;
378  return D3DFMT_X8R8G8B8;
380  return D3DFMT_A8R8G8B8;
383  return D3DFMT_L8;
384  default:
385  return D3DFMT_UNKNOWN;
386  }
387 }
388 
389 static Uint32
390 D3DFMTToPixelFormat(D3DFORMAT format)
391 {
392  switch (format) {
393  case D3DFMT_R5G6B5:
394  return SDL_PIXELFORMAT_RGB565;
395  case D3DFMT_X8R8G8B8:
396  return SDL_PIXELFORMAT_RGB888;
397  case D3DFMT_A8R8G8B8:
399  default:
401  }
402 }
403 
404 static void
405 D3D_InitRenderState(D3D_RenderData *data)
406 {
408 
409  IDirect3DDevice9 *device = data->device;
410 
416 
417  /* Enable color modulation by diffuse color */
421  D3DTA_TEXTURE);
423  D3DTA_DIFFUSE);
424 
425  /* Enable alpha modulation by diffuse alpha */
429  D3DTA_TEXTURE);
431  D3DTA_DIFFUSE);
432 
433  /* Enable separate alpha blend function, if possible */
434  if (data->enableSeparateAlphaBlend) {
436  }
437 
438  /* Disable second texture stage, since we're done */
443 
444  /* Set an identity world and view matrix */
445  matrix.m[0][0] = 1.0f;
446  matrix.m[0][1] = 0.0f;
447  matrix.m[0][2] = 0.0f;
448  matrix.m[0][3] = 0.0f;
449  matrix.m[1][0] = 0.0f;
450  matrix.m[1][1] = 1.0f;
451  matrix.m[1][2] = 0.0f;
452  matrix.m[1][3] = 0.0f;
453  matrix.m[2][0] = 0.0f;
454  matrix.m[2][1] = 0.0f;
455  matrix.m[2][2] = 1.0f;
456  matrix.m[2][3] = 0.0f;
457  matrix.m[3][0] = 0.0f;
458  matrix.m[3][1] = 0.0f;
459  matrix.m[3][2] = 0.0f;
460  matrix.m[3][3] = 1.0f;
461  IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &matrix);
462  IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
463 
464  /* Reset our current scale mode */
465  SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
466 
467  /* Start the render with beginScene */
468  data->beginScene = SDL_TRUE;
469 }
470 
471 static int
472 D3D_Reset(SDL_Renderer * renderer)
473 {
474  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
475  HRESULT result;
476 
477  /* Release the default render target before reset */
478  if (data->defaultRenderTarget) {
479  IDirect3DSurface9_Release(data->defaultRenderTarget);
480  data->defaultRenderTarget = NULL;
481  }
482 
483  result = IDirect3DDevice9_Reset(data->device, &data->pparams);
484  if (FAILED(result)) {
485  if (result == D3DERR_DEVICELOST) {
486  /* Don't worry about it, we'll reset later... */
487  return 0;
488  } else {
489  return D3D_SetError("Reset()", result);
490  }
491  }
492 
493  IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
494  D3D_InitRenderState(data);
495  D3D_UpdateViewport(renderer);
496  return 0;
497 }
498 
499 static int
500 D3D_ActivateRenderer(SDL_Renderer * renderer)
501 {
502  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
503  HRESULT result;
504 
505  if (data->updateSize) {
506  SDL_Window *window = renderer->window;
507  int w, h;
508 
509  SDL_GetWindowSize(window, &w, &h);
510  data->pparams.BackBufferWidth = w;
511  data->pparams.BackBufferHeight = h;
513  data->pparams.BackBufferFormat =
514  PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));
515  } else {
516  data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
517  }
518  if (D3D_Reset(renderer) < 0) {
519  return -1;
520  }
521 
522  data->updateSize = SDL_FALSE;
523  }
524  if (data->beginScene) {
525  result = IDirect3DDevice9_BeginScene(data->device);
526  if (result == D3DERR_DEVICELOST) {
527  if (D3D_Reset(renderer) < 0) {
528  return -1;
529  }
530  result = IDirect3DDevice9_BeginScene(data->device);
531  }
532  if (FAILED(result)) {
533  return D3D_SetError("BeginScene()", result);
534  }
535  data->beginScene = SDL_FALSE;
536  }
537  return 0;
538 }
539 
540 SDL_Renderer *
541 D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
542 {
543  SDL_Renderer *renderer;
544  D3D_RenderData *data;
545  SDL_SysWMinfo windowinfo;
546  HRESULT result;
547  const char *hint;
548  D3DPRESENT_PARAMETERS pparams;
549  IDirect3DSwapChain9 *chain;
550  D3DCAPS9 caps;
551  DWORD device_flags;
552  Uint32 window_flags;
553  int w, h;
554  SDL_DisplayMode fullscreen_mode;
555  int d3dxVersion;
556  char d3dxDLLFile[50];
557  int displayIndex;
558 
559  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
560  if (!renderer) {
561  SDL_OutOfMemory();
562  return NULL;
563  }
564 
565  data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
566  if (!data) {
567  SDL_free(renderer);
568  SDL_OutOfMemory();
569  return NULL;
570  }
571 
572  if( D3D_LoadDLL( &data->d3dDLL, &data->d3d ) ) {
573  for (d3dxVersion=50;d3dxVersion>0;d3dxVersion--) {
574  LPTSTR dllName;
575  SDL_snprintf(d3dxDLLFile, sizeof(d3dxDLLFile), "D3DX9_%02d.dll", d3dxVersion);
576  dllName = WIN_UTF8ToString(d3dxDLLFile);
577  data->d3dxDLL = (void *)LoadLibrary(dllName); /* not using SDL_LoadObject() as we want silently fail - no error message */
578  SDL_free(dllName);
579  if (data->d3dxDLL) {
580  HRESULT (WINAPI *D3DXCreateMatrixStack) (DWORD Flags, LPD3DXMATRIXSTACK* ppStack);
581  D3DXCreateMatrixStack = (HRESULT (WINAPI *) (DWORD, LPD3DXMATRIXSTACK*)) SDL_LoadFunction(data->d3dxDLL, "D3DXCreateMatrixStack");
582  if (D3DXCreateMatrixStack) {
583  D3DXCreateMatrixStack(0, &data->matrixStack);
584  break;
585  }
586  }
587  }
588 
589  if (!data->matrixStack) {
590  if (data->d3dxDLL) SDL_UnloadObject(data->d3dxDLL);
591  }
592  }
593 
594  if (!data->d3d || !data->matrixStack) {
595  SDL_free(renderer);
596  SDL_free(data);
597  SDL_SetError("Unable to create Direct3D interface");
598  return NULL;
599  }
600 
601  renderer->WindowEvent = D3D_WindowEvent;
602  renderer->CreateTexture = D3D_CreateTexture;
603  renderer->UpdateTexture = D3D_UpdateTexture;
604  renderer->UpdateTextureYUV = D3D_UpdateTextureYUV;
605  renderer->LockTexture = D3D_LockTexture;
606  renderer->UnlockTexture = D3D_UnlockTexture;
607  renderer->SetRenderTarget = D3D_SetRenderTarget;
608  renderer->UpdateViewport = D3D_UpdateViewport;
609  renderer->UpdateClipRect = D3D_UpdateClipRect;
610  renderer->RenderClear = D3D_RenderClear;
611  renderer->RenderDrawPoints = D3D_RenderDrawPoints;
612  renderer->RenderDrawLines = D3D_RenderDrawLines;
613  renderer->RenderFillRects = D3D_RenderFillRects;
614  renderer->RenderCopy = D3D_RenderCopy;
615  renderer->RenderCopyEx = D3D_RenderCopyEx;
616  renderer->RenderReadPixels = D3D_RenderReadPixels;
617  renderer->RenderPresent = D3D_RenderPresent;
618  renderer->DestroyTexture = D3D_DestroyTexture;
619  renderer->DestroyRenderer = D3D_DestroyRenderer;
620  renderer->info = D3D_RenderDriver.info;
621  renderer->driverdata = data;
622 
623  renderer->info.flags = SDL_RENDERER_ACCELERATED;
624 
625  SDL_VERSION(&windowinfo.version);
626  SDL_GetWindowWMInfo(window, &windowinfo);
627 
628  window_flags = SDL_GetWindowFlags(window);
629  SDL_GetWindowSize(window, &w, &h);
630  SDL_GetWindowDisplayMode(window, &fullscreen_mode);
631 
632  SDL_zero(pparams);
633  pparams.hDeviceWindow = windowinfo.info.win.window;
634  pparams.BackBufferWidth = w;
635  pparams.BackBufferHeight = h;
636  if (window_flags & SDL_WINDOW_FULLSCREEN) {
637  pparams.BackBufferFormat =
638  PixelFormatToD3DFMT(fullscreen_mode.format);
639  } else {
641  }
642  pparams.BackBufferCount = 1;
644 
645  if (window_flags & SDL_WINDOW_FULLSCREEN) {
646  if ( ( window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP ) {
647  pparams.Windowed = TRUE;
648  pparams.FullScreen_RefreshRateInHz = 0;
649  } else {
650  pparams.Windowed = FALSE;
652  fullscreen_mode.refresh_rate;
653  }
654  } else {
655  pparams.Windowed = TRUE;
656  pparams.FullScreen_RefreshRateInHz = 0;
657  }
658  if (flags & SDL_RENDERER_PRESENTVSYNC) {
660  } else {
662  }
663 
664  /* Get the adapter for the display that the window is on */
665  displayIndex = SDL_GetWindowDisplayIndex( window );
666  data->adapter = SDL_Direct3D9GetAdapterIndex( displayIndex );
667 
668  IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
669 
670  device_flags = D3DCREATE_FPU_PRESERVE;
672  device_flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
673  } else {
674  device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
675  }
676 
678  if (hint && SDL_atoi(hint)) {
679  device_flags |= D3DCREATE_MULTITHREADED;
680  }
681 
682  result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
684  pparams.hDeviceWindow,
685  device_flags,
686  &pparams, &data->device);
687  if (FAILED(result)) {
688  D3D_DestroyRenderer(renderer);
689  D3D_SetError("CreateDevice()", result);
690  return NULL;
691  }
692 
693  /* Get presentation parameters to fill info */
694  result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
695  if (FAILED(result)) {
696  D3D_DestroyRenderer(renderer);
697  D3D_SetError("GetSwapChain()", result);
698  return NULL;
699  }
700  result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
701  if (FAILED(result)) {
703  D3D_DestroyRenderer(renderer);
704  D3D_SetError("GetPresentParameters()", result);
705  return NULL;
706  }
709  renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
710  }
711  data->pparams = pparams;
712 
713  IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
714  renderer->info.max_texture_width = caps.MaxTextureWidth;
715  renderer->info.max_texture_height = caps.MaxTextureHeight;
716  if (caps.NumSimultaneousRTs >= 2) {
718  }
719 
721  data->enableSeparateAlphaBlend = SDL_TRUE;
722  }
723 
724  /* Store the default render target */
725  IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget );
726  data->currentRenderTarget = NULL;
727 
728  /* Set up parameters for rendering */
729  D3D_InitRenderState(data);
730 
731  if (caps.MaxSimultaneousTextures >= 3)
732  {
733 #ifdef ASSEMBLE_SHADER
734  /* This shader was created by running the following HLSL through the fxc compiler
735  and then tuning the generated assembly.
736 
737  fxc /T fx_4_0 /O3 /Gfa /Fc yuv.fxc yuv.fx
738 
739  --- yuv.fx ---
740  Texture2D g_txY;
741  Texture2D g_txU;
742  Texture2D g_txV;
743 
744  SamplerState samLinear
745  {
746  Filter = ANISOTROPIC;
747  AddressU = Clamp;
748  AddressV = Clamp;
749  MaxAnisotropy = 1;
750  };
751 
752  struct VS_OUTPUT
753  {
754  float2 TextureUV : TEXCOORD0;
755  };
756 
757  struct PS_OUTPUT
758  {
759  float4 RGBAColor : SV_Target;
760  };
761 
762  PS_OUTPUT YUV420( VS_OUTPUT In )
763  {
764  const float3 offset = {-0.0625, -0.5, -0.5};
765  const float3 Rcoeff = {1.164, 0.000, 1.596};
766  const float3 Gcoeff = {1.164, -0.391, -0.813};
767  const float3 Bcoeff = {1.164, 2.018, 0.000};
768 
769  PS_OUTPUT Output;
770  float2 TextureUV = In.TextureUV;
771 
772  float3 yuv;
773  yuv.x = g_txY.Sample( samLinear, TextureUV ).r;
774  yuv.y = g_txU.Sample( samLinear, TextureUV ).r;
775  yuv.z = g_txV.Sample( samLinear, TextureUV ).r;
776 
777  yuv += offset;
778  Output.RGBAColor.r = dot(yuv, Rcoeff);
779  Output.RGBAColor.g = dot(yuv, Gcoeff);
780  Output.RGBAColor.b = dot(yuv, Bcoeff);
781  Output.RGBAColor.a = 1.0f;
782 
783  return Output;
784  }
785 
786  technique10 RenderYUV420
787  {
788  pass P0
789  {
790  SetPixelShader( CompileShader( ps_4_0_level_9_0, YUV420() ) );
791  }
792  }
793  */
794  const char *shader_text =
795  "ps_2_0\n"
796  "def c0, -0.0625, -0.5, -0.5, 1\n"
797  "def c1, 1.16400003, 0, 1.59599996, 0\n"
798  "def c2, 1.16400003, -0.391000003, -0.813000023, 0\n"
799  "def c3, 1.16400003, 2.01799989, 0, 0\n"
800  "dcl t0.xy\n"
801  "dcl v0.xyzw\n"
802  "dcl_2d s0\n"
803  "dcl_2d s1\n"
804  "dcl_2d s2\n"
805  "texld r0, t0, s0\n"
806  "texld r1, t0, s1\n"
807  "texld r2, t0, s2\n"
808  "mov r0.y, r1.x\n"
809  "mov r0.z, r2.x\n"
810  "add r0.xyz, r0, c0\n"
811  "dp3 r1.x, r0, c1\n"
812  "dp3 r1.y, r0, c2\n"
813  "dp2add r1.z, r0, c3, c3.z\n" /* Logically this is "dp3 r1.z, r0, c3" but the optimizer did its magic */
814  "mov r1.w, c0.w\n"
815  "mul r0, r1, v0\n" /* Not in the HLSL, multiply by vertex color */
816  "mov oC0, r0\n"
817  ;
818  LPD3DXBUFFER pCode;
819  LPD3DXBUFFER pErrorMsgs;
820  LPDWORD shader_data = NULL;
821  DWORD shader_size = 0;
822  result = D3DXAssembleShader(shader_text, SDL_strlen(shader_text), NULL, NULL, 0, &pCode, &pErrorMsgs);
823  if (!FAILED(result)) {
824  shader_data = (DWORD*)pCode->lpVtbl->GetBufferPointer(pCode);
825  shader_size = pCode->lpVtbl->GetBufferSize(pCode);
826  PrintShaderData(shader_data, shader_size);
827  } else {
828  const char *error = (const char *)pErrorMsgs->lpVtbl->GetBufferPointer(pErrorMsgs);
829  SDL_SetError("Couldn't assemble shader: %s", error);
830  }
831 #else
832  const DWORD shader_data[] = {
833  0xffff0200, 0x05000051, 0xa00f0000, 0xbd800000, 0xbf000000, 0xbf000000,
834  0x3f800000, 0x05000051, 0xa00f0001, 0x3f94fdf4, 0x00000000, 0x3fcc49ba,
835  0x00000000, 0x05000051, 0xa00f0002, 0x3f94fdf4, 0xbec83127, 0xbf5020c5,
836  0x00000000, 0x05000051, 0xa00f0003, 0x3f94fdf4, 0x400126e9, 0x00000000,
837  0x00000000, 0x0200001f, 0x80000000, 0xb0030000, 0x0200001f, 0x80000000,
838  0x900f0000, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000,
839  0xa00f0801, 0x0200001f, 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000,
840  0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801,
841  0x03000042, 0x800f0002, 0xb0e40000, 0xa0e40802, 0x02000001, 0x80020000,
842  0x80000001, 0x02000001, 0x80040000, 0x80000002, 0x03000002, 0x80070000,
843  0x80e40000, 0xa0e40000, 0x03000008, 0x80010001, 0x80e40000, 0xa0e40001,
844  0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001,
845  0x80e40000, 0xa0e40003, 0xa0aa0003, 0x02000001, 0x80080001, 0xa0ff0000,
846  0x03000005, 0x800f0000, 0x80e40001, 0x90e40000, 0x02000001, 0x800f0800,
847  0x80e40000, 0x0000ffff
848  };
849 #endif
850  if (shader_data != NULL) {
851  result = IDirect3DDevice9_CreatePixelShader(data->device, shader_data, &data->ps_yuv);
852  if (!FAILED(result)) {
855  } else {
856  D3D_SetError("CreatePixelShader()", result);
857  }
858  }
859  }
860 
861  return renderer;
862 }
863 
864 static void
865 D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
866 {
867  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
868 
870  data->updateSize = SDL_TRUE;
871  }
872 }
873 
875 GetScaleQuality(void)
876 {
877  const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
878 
879  if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
880  return D3DTEXF_POINT;
881  } else /* if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) */ {
882  return D3DTEXF_LINEAR;
883  }
884 }
885 
886 static int
887 D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
888 {
889  D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
890  D3D_TextureData *data;
891  D3DPOOL pool;
892  DWORD usage;
893  HRESULT result;
894 
895  data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
896  if (!data) {
897  return SDL_OutOfMemory();
898  }
899  data->scaleMode = GetScaleQuality();
900 
901  texture->driverdata = data;
902 
903 #ifdef USE_DYNAMIC_TEXTURE
904  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
905  pool = D3DPOOL_DEFAULT;
907  } else
908 #endif
909  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
910  /* D3DPOOL_MANAGED does not work with D3DUSAGE_RENDERTARGET */
911  pool = D3DPOOL_DEFAULT;
913  } else {
914  pool = D3DPOOL_MANAGED;
915  usage = 0;
916  }
917 
918  result =
919  IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
920  texture->h, 1, usage,
921  PixelFormatToD3DFMT(texture->format),
922  pool, &data->texture, NULL);
923  if (FAILED(result)) {
924  return D3D_SetError("CreateTexture()", result);
925  }
926 
927  if (texture->format == SDL_PIXELFORMAT_YV12 ||
928  texture->format == SDL_PIXELFORMAT_IYUV) {
929  data->yuv = SDL_TRUE;
930 
931  result =
932  IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
933  texture->h / 2, 1, usage,
934  PixelFormatToD3DFMT(texture->format),
935  pool, &data->utexture, NULL);
936  if (FAILED(result)) {
937  return D3D_SetError("CreateTexture()", result);
938  }
939 
940  result =
941  IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
942  texture->h / 2, 1, usage,
943  PixelFormatToD3DFMT(texture->format),
944  pool, &data->vtexture, NULL);
945  if (FAILED(result)) {
946  return D3D_SetError("CreateTexture()", result);
947  }
948  }
949 
950  return 0;
951 }
952 
953 static int
954 D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool full_texture, int x, int y, int w, int h, const void *pixels, int pitch)
955 {
956  RECT d3drect;
957  D3DLOCKED_RECT locked;
958  const Uint8 *src;
959  Uint8 *dst;
960  int row, length;
961  HRESULT result;
962 
963  if (full_texture) {
964  result = IDirect3DTexture9_LockRect(texture, 0, &locked, NULL, D3DLOCK_DISCARD);
965  } else {
966  d3drect.left = x;
967  d3drect.right = x + w;
968  d3drect.top = y;
969  d3drect.bottom = y + h;
970  result = IDirect3DTexture9_LockRect(texture, 0, &locked, &d3drect, 0);
971  }
972 
973  if (FAILED(result)) {
974  return D3D_SetError("LockRect()", result);
975  }
976 
977  src = (const Uint8 *)pixels;
978  dst = locked.pBits;
979  length = w * SDL_BYTESPERPIXEL(format);
980  if (length == pitch && length == locked.Pitch) {
981  SDL_memcpy(dst, src, length*h);
982  } else {
983  for (row = 0; row < h; ++row) {
984  SDL_memcpy(dst, src, length);
985  src += pitch;
986  dst += locked.Pitch;
987  }
988  }
989  IDirect3DTexture9_UnlockRect(texture, 0);
990 
991  return 0;
992 }
993 
994 static int
995 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
996  const SDL_Rect * rect, const void *pixels, int pitch)
997 {
998  D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
999  SDL_bool full_texture = SDL_FALSE;
1000 
1001 #ifdef USE_DYNAMIC_TEXTURE
1002  if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
1003  rect->x == 0 && rect->y == 0 &&
1004  rect->w == texture->w && rect->h == texture->h) {
1005  full_texture = SDL_TRUE;
1006  }
1007 #endif
1008 
1009  if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
1010  return -1;
1011  }
1012 
1013  if (data->yuv) {
1014  /* Skip to the correct offset into the next texture */
1015  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
1016 
1017  if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->vtexture : data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
1018  return -1;
1019  }
1020 
1021  /* Skip to the correct offset into the next texture */
1022  pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
1023  if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->utexture : data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
1024  return -1;
1025  }
1026  }
1027  return 0;
1028 }
1029 
1030 static int
1031 D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
1032  const SDL_Rect * rect,
1033  const Uint8 *Yplane, int Ypitch,
1034  const Uint8 *Uplane, int Upitch,
1035  const Uint8 *Vplane, int Vpitch)
1036 {
1037  D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1038  SDL_bool full_texture = SDL_FALSE;
1039 
1040 #ifdef USE_DYNAMIC_TEXTURE
1041  if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
1042  rect->x == 0 && rect->y == 0 &&
1043  rect->w == texture->w && rect->h == texture->h) {
1044  full_texture = SDL_TRUE;
1045  }
1046 #endif
1047 
1048  if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
1049  return -1;
1050  }
1051  if (D3D_UpdateTextureInternal(data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch) < 0) {
1052  return -1;
1053  }
1054  if (D3D_UpdateTextureInternal(data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch) < 0) {
1055  return -1;
1056  }
1057  return 0;
1058 }
1059 
1060 static int
1061 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1062  const SDL_Rect * rect, void **pixels, int *pitch)
1063 {
1064  D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1065  RECT d3drect;
1066  D3DLOCKED_RECT locked;
1067  HRESULT result;
1068 
1069  if (data->yuv) {
1070  /* It's more efficient to upload directly... */
1071  if (!data->pixels) {
1072  data->pitch = texture->w;
1073  data->pixels = (Uint8 *)SDL_malloc((texture->h * data->pitch * 3) / 2);
1074  if (!data->pixels) {
1075  return SDL_OutOfMemory();
1076  }
1077  }
1078  data->locked_rect = *rect;
1079  *pixels =
1080  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
1081  rect->x * SDL_BYTESPERPIXEL(texture->format));
1082  *pitch = data->pitch;
1083  } else {
1084  d3drect.left = rect->x;
1085  d3drect.right = rect->x + rect->w;
1086  d3drect.top = rect->y;
1087  d3drect.bottom = rect->y + rect->h;
1088 
1089  result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
1090  if (FAILED(result)) {
1091  return D3D_SetError("LockRect()", result);
1092  }
1093  *pixels = locked.pBits;
1094  *pitch = locked.Pitch;
1095  }
1096  return 0;
1097 }
1098 
1099 static void
1100 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1101 {
1102  D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1103 
1104  if (data->yuv) {
1105  const SDL_Rect *rect = &data->locked_rect;
1106  void *pixels =
1107  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
1108  rect->x * SDL_BYTESPERPIXEL(texture->format));
1109  D3D_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
1110  } else {
1111  IDirect3DTexture9_UnlockRect(data->texture, 0);
1112  }
1113 }
1114 
1115 static int
1116 D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1117 {
1118  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1119  D3D_TextureData *texturedata;
1120  HRESULT result;
1121 
1122  D3D_ActivateRenderer(renderer);
1123 
1124  /* Release the previous render target if it wasn't the default one */
1125  if (data->currentRenderTarget != NULL) {
1126  IDirect3DSurface9_Release(data->currentRenderTarget);
1127  data->currentRenderTarget = NULL;
1128  }
1129 
1130  if (texture == NULL) {
1131  IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
1132  return 0;
1133  }
1134 
1135  texturedata = (D3D_TextureData *) texture->driverdata;
1136  result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture, 0, &data->currentRenderTarget);
1137  if(FAILED(result)) {
1138  return D3D_SetError("GetSurfaceLevel()", result);
1139  }
1140  result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget);
1141  if(FAILED(result)) {
1142  return D3D_SetError("SetRenderTarget()", result);
1143  }
1144 
1145  return 0;
1146 }
1147 
1148 static int
1149 D3D_UpdateViewport(SDL_Renderer * renderer)
1150 {
1151  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1152  D3DVIEWPORT9 viewport;
1153  D3DMATRIX matrix;
1154 
1155  /* Set the viewport */
1156  viewport.X = renderer->viewport.x;
1157  viewport.Y = renderer->viewport.y;
1158  viewport.Width = renderer->viewport.w;
1159  viewport.Height = renderer->viewport.h;
1160  viewport.MinZ = 0.0f;
1161  viewport.MaxZ = 1.0f;
1162  IDirect3DDevice9_SetViewport(data->device, &viewport);
1163 
1164  /* Set an orthographic projection matrix */
1165  if (renderer->viewport.w && renderer->viewport.h) {
1166  matrix.m[0][0] = 2.0f / renderer->viewport.w;
1167  matrix.m[0][1] = 0.0f;
1168  matrix.m[0][2] = 0.0f;
1169  matrix.m[0][3] = 0.0f;
1170  matrix.m[1][0] = 0.0f;
1171  matrix.m[1][1] = -2.0f / renderer->viewport.h;
1172  matrix.m[1][2] = 0.0f;
1173  matrix.m[1][3] = 0.0f;
1174  matrix.m[2][0] = 0.0f;
1175  matrix.m[2][1] = 0.0f;
1176  matrix.m[2][2] = 1.0f;
1177  matrix.m[2][3] = 0.0f;
1178  matrix.m[3][0] = -1.0f;
1179  matrix.m[3][1] = 1.0f;
1180  matrix.m[3][2] = 0.0f;
1181  matrix.m[3][3] = 1.0f;
1182  IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
1183  }
1184 
1185  return 0;
1186 }
1187 
1188 static int
1189 D3D_UpdateClipRect(SDL_Renderer * renderer)
1190 {
1191  const SDL_Rect *rect = &renderer->clip_rect;
1192  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1193  RECT r;
1194  HRESULT result;
1195 
1196  if (!SDL_RectEmpty(rect)) {
1198  r.left = rect->x;
1199  r.top = rect->y;
1200  r.right = rect->x + rect->w;
1201  r.bottom = rect->y + rect->h;
1202 
1203  result = IDirect3DDevice9_SetScissorRect(data->device, &r);
1204  if (result != D3D_OK) {
1205  D3D_SetError("SetScissor()", result);
1206  return -1;
1207  }
1208  } else {
1210  }
1211  return 0;
1212 }
1213 
1214 static int
1215 D3D_RenderClear(SDL_Renderer * renderer)
1216 {
1217  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1218  DWORD color;
1219  HRESULT result;
1220 
1221  if (D3D_ActivateRenderer(renderer) < 0) {
1222  return -1;
1223  }
1224 
1225  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1226 
1227  /* Don't reset the viewport if we don't have to! */
1228  if (!renderer->viewport.x && !renderer->viewport.y &&
1229  renderer->viewport.w == data->pparams.BackBufferWidth &&
1230  renderer->viewport.h == data->pparams.BackBufferHeight) {
1231  result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
1232  } else {
1233  D3DVIEWPORT9 viewport;
1234 
1235  /* Clear is defined to clear the entire render target */
1236  viewport.X = 0;
1237  viewport.Y = 0;
1238  viewport.Width = data->pparams.BackBufferWidth;
1239  viewport.Height = data->pparams.BackBufferHeight;
1240  viewport.MinZ = 0.0f;
1241  viewport.MaxZ = 1.0f;
1242  IDirect3DDevice9_SetViewport(data->device, &viewport);
1243 
1244  result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
1245 
1246  /* Reset the viewport */
1247  viewport.X = renderer->viewport.x;
1248  viewport.Y = renderer->viewport.y;
1249  viewport.Width = renderer->viewport.w;
1250  viewport.Height = renderer->viewport.h;
1251  viewport.MinZ = 0.0f;
1252  viewport.MaxZ = 1.0f;
1253  IDirect3DDevice9_SetViewport(data->device, &viewport);
1254  }
1255 
1256  if (FAILED(result)) {
1257  return D3D_SetError("Clear()", result);
1258  }
1259  return 0;
1260 }
1261 
1262 static void
1263 D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
1264 {
1265  switch (blendMode) {
1266  case SDL_BLENDMODE_NONE:
1268  FALSE);
1269  break;
1270  case SDL_BLENDMODE_BLEND:
1272  TRUE);
1277  if (data->enableSeparateAlphaBlend) {
1279  D3DBLEND_ONE);
1282  }
1283  break;
1284  case SDL_BLENDMODE_ADD:
1286  TRUE);
1290  D3DBLEND_ONE);
1291  if (data->enableSeparateAlphaBlend) {
1293  D3DBLEND_ZERO);
1295  D3DBLEND_ONE);
1296  }
1297  break;
1298  case SDL_BLENDMODE_MOD:
1300  TRUE);
1302  D3DBLEND_ZERO);
1305  if (data->enableSeparateAlphaBlend) {
1307  D3DBLEND_ZERO);
1309  D3DBLEND_ONE);
1310  }
1311  break;
1312  }
1313 }
1314 
1315 static int
1316 D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
1317  int count)
1318 {
1319  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1320  DWORD color;
1321  Vertex *vertices;
1322  int i;
1323  HRESULT result;
1324 
1325  if (D3D_ActivateRenderer(renderer) < 0) {
1326  return -1;
1327  }
1328 
1329  D3D_SetBlendMode(data, renderer->blendMode);
1330 
1331  result =
1332  IDirect3DDevice9_SetTexture(data->device, 0,
1333  (IDirect3DBaseTexture9 *) 0);
1334  if (FAILED(result)) {
1335  return D3D_SetError("SetTexture()", result);
1336  }
1337 
1338  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1339 
1340  vertices = SDL_stack_alloc(Vertex, count);
1341  for (i = 0; i < count; ++i) {
1342  vertices[i].x = points[i].x;
1343  vertices[i].y = points[i].y;
1344  vertices[i].z = 0.0f;
1345  vertices[i].color = color;
1346  vertices[i].u = 0.0f;
1347  vertices[i].v = 0.0f;
1348  }
1349  result =
1351  vertices, sizeof(*vertices));
1353  if (FAILED(result)) {
1354  return D3D_SetError("DrawPrimitiveUP()", result);
1355  }
1356  return 0;
1357 }
1358 
1359 static int
1360 D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
1361  int count)
1362 {
1363  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1364  DWORD color;
1365  Vertex *vertices;
1366  int i;
1367  HRESULT result;
1368 
1369  if (D3D_ActivateRenderer(renderer) < 0) {
1370  return -1;
1371  }
1372 
1373  D3D_SetBlendMode(data, renderer->blendMode);
1374 
1375  result =
1376  IDirect3DDevice9_SetTexture(data->device, 0,
1377  (IDirect3DBaseTexture9 *) 0);
1378  if (FAILED(result)) {
1379  return D3D_SetError("SetTexture()", result);
1380  }
1381 
1382  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1383 
1384  vertices = SDL_stack_alloc(Vertex, count);
1385  for (i = 0; i < count; ++i) {
1386  vertices[i].x = points[i].x;
1387  vertices[i].y = points[i].y;
1388  vertices[i].z = 0.0f;
1389  vertices[i].color = color;
1390  vertices[i].u = 0.0f;
1391  vertices[i].v = 0.0f;
1392  }
1393  result =
1394  IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
1395  vertices, sizeof(*vertices));
1396 
1397  /* DirectX 9 has the same line rasterization semantics as GDI,
1398  so we need to close the endpoint of the line */
1399  if (count == 2 ||
1400  points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1401  vertices[0].x = points[count-1].x;
1402  vertices[0].y = points[count-1].y;
1403  result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
1404  }
1405 
1407  if (FAILED(result)) {
1408  return D3D_SetError("DrawPrimitiveUP()", result);
1409  }
1410  return 0;
1411 }
1412 
1413 static int
1414 D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
1415  int count)
1416 {
1417  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1418  DWORD color;
1419  int i;
1420  float minx, miny, maxx, maxy;
1421  Vertex vertices[4];
1422  HRESULT result;
1423 
1424  if (D3D_ActivateRenderer(renderer) < 0) {
1425  return -1;
1426  }
1427 
1428  D3D_SetBlendMode(data, renderer->blendMode);
1429 
1430  result =
1431  IDirect3DDevice9_SetTexture(data->device, 0,
1432  (IDirect3DBaseTexture9 *) 0);
1433  if (FAILED(result)) {
1434  return D3D_SetError("SetTexture()", result);
1435  }
1436 
1437  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1438 
1439  for (i = 0; i < count; ++i) {
1440  const SDL_FRect *rect = &rects[i];
1441 
1442  minx = rect->x;
1443  miny = rect->y;
1444  maxx = rect->x + rect->w;
1445  maxy = rect->y + rect->h;
1446 
1447  vertices[0].x = minx;
1448  vertices[0].y = miny;
1449  vertices[0].z = 0.0f;
1450  vertices[0].color = color;
1451  vertices[0].u = 0.0f;
1452  vertices[0].v = 0.0f;
1453 
1454  vertices[1].x = maxx;
1455  vertices[1].y = miny;
1456  vertices[1].z = 0.0f;
1457  vertices[1].color = color;
1458  vertices[1].u = 0.0f;
1459  vertices[1].v = 0.0f;
1460 
1461  vertices[2].x = maxx;
1462  vertices[2].y = maxy;
1463  vertices[2].z = 0.0f;
1464  vertices[2].color = color;
1465  vertices[2].u = 0.0f;
1466  vertices[2].v = 0.0f;
1467 
1468  vertices[3].x = minx;
1469  vertices[3].y = maxy;
1470  vertices[3].z = 0.0f;
1471  vertices[3].color = color;
1472  vertices[3].u = 0.0f;
1473  vertices[3].v = 0.0f;
1474 
1475  result =
1477  2, vertices, sizeof(*vertices));
1478  if (FAILED(result)) {
1479  return D3D_SetError("DrawPrimitiveUP()", result);
1480  }
1481  }
1482  return 0;
1483 }
1484 
1485 static void
1486 D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
1487 {
1488  if (texturedata->scaleMode != data->scaleMode[index]) {
1490  texturedata->scaleMode);
1492  texturedata->scaleMode);
1493  data->scaleMode[index] = texturedata->scaleMode;
1494  }
1495 }
1496 
1497 static int
1498 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1499  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1500 {
1501  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1502  D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
1504  float minx, miny, maxx, maxy;
1505  float minu, maxu, minv, maxv;
1506  DWORD color;
1507  Vertex vertices[4];
1508  HRESULT result;
1509 
1510  if (D3D_ActivateRenderer(renderer) < 0) {
1511  return -1;
1512  }
1513 
1514  minx = dstrect->x - 0.5f;
1515  miny = dstrect->y - 0.5f;
1516  maxx = dstrect->x + dstrect->w - 0.5f;
1517  maxy = dstrect->y + dstrect->h - 0.5f;
1518 
1519  minu = (float) srcrect->x / texture->w;
1520  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1521  minv = (float) srcrect->y / texture->h;
1522  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1523 
1524  color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1525 
1526  vertices[0].x = minx;
1527  vertices[0].y = miny;
1528  vertices[0].z = 0.0f;
1529  vertices[0].color = color;
1530  vertices[0].u = minu;
1531  vertices[0].v = minv;
1532 
1533  vertices[1].x = maxx;
1534  vertices[1].y = miny;
1535  vertices[1].z = 0.0f;
1536  vertices[1].color = color;
1537  vertices[1].u = maxu;
1538  vertices[1].v = minv;
1539 
1540  vertices[2].x = maxx;
1541  vertices[2].y = maxy;
1542  vertices[2].z = 0.0f;
1543  vertices[2].color = color;
1544  vertices[2].u = maxu;
1545  vertices[2].v = maxv;
1546 
1547  vertices[3].x = minx;
1548  vertices[3].y = maxy;
1549  vertices[3].z = 0.0f;
1550  vertices[3].color = color;
1551  vertices[3].u = minu;
1552  vertices[3].v = maxv;
1553 
1554  D3D_SetBlendMode(data, texture->blendMode);
1555 
1556  D3D_UpdateTextureScaleMode(data, texturedata, 0);
1557 
1558  result =
1560  texturedata->texture);
1561  if (FAILED(result)) {
1562  return D3D_SetError("SetTexture()", result);
1563  }
1564 
1565  if (texturedata->yuv) {
1566  shader = data->ps_yuv;
1567 
1568  D3D_UpdateTextureScaleMode(data, texturedata, 1);
1569  D3D_UpdateTextureScaleMode(data, texturedata, 2);
1570 
1571  result =
1573  texturedata->utexture);
1574  if (FAILED(result)) {
1575  return D3D_SetError("SetTexture()", result);
1576  }
1577 
1578  result =
1580  texturedata->vtexture);
1581  if (FAILED(result)) {
1582  return D3D_SetError("SetTexture()", result);
1583  }
1584  }
1585 
1586  if (shader) {
1587  result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1588  if (FAILED(result)) {
1589  return D3D_SetError("SetShader()", result);
1590  }
1591  }
1592  result =
1594  vertices, sizeof(*vertices));
1595  if (FAILED(result)) {
1596  return D3D_SetError("DrawPrimitiveUP()", result);
1597  }
1598  if (shader) {
1599  result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
1600  if (FAILED(result)) {
1601  return D3D_SetError("SetShader()", result);
1602  }
1603  }
1604  return 0;
1605 }
1606 
1607 
1608 static int
1609 D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1610  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1611  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
1612 {
1613  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1614  D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
1615  LPDIRECT3DPIXELSHADER9 shader = NULL;
1616  float minx, miny, maxx, maxy;
1617  float minu, maxu, minv, maxv;
1618  float centerx, centery;
1619  DWORD color;
1620  Vertex vertices[4];
1621  HRESULT result;
1622 
1623  if (D3D_ActivateRenderer(renderer) < 0) {
1624  return -1;
1625  }
1626 
1627  centerx = center->x;
1628  centery = center->y;
1629 
1630  if (flip & SDL_FLIP_HORIZONTAL) {
1631  minx = dstrect->w - centerx - 0.5f;
1632  maxx = -centerx - 0.5f;
1633  }
1634  else {
1635  minx = -centerx - 0.5f;
1636  maxx = dstrect->w - centerx - 0.5f;
1637  }
1638 
1639  if (flip & SDL_FLIP_VERTICAL) {
1640  miny = dstrect->h - centery - 0.5f;
1641  maxy = -centery - 0.5f;
1642  }
1643  else {
1644  miny = -centery - 0.5f;
1645  maxy = dstrect->h - centery - 0.5f;
1646  }
1647 
1648  minu = (float) srcrect->x / texture->w;
1649  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1650  minv = (float) srcrect->y / texture->h;
1651  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1652 
1653  color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1654 
1655  vertices[0].x = minx;
1656  vertices[0].y = miny;
1657  vertices[0].z = 0.0f;
1658  vertices[0].color = color;
1659  vertices[0].u = minu;
1660  vertices[0].v = minv;
1661 
1662  vertices[1].x = maxx;
1663  vertices[1].y = miny;
1664  vertices[1].z = 0.0f;
1665  vertices[1].color = color;
1666  vertices[1].u = maxu;
1667  vertices[1].v = minv;
1668 
1669  vertices[2].x = maxx;
1670  vertices[2].y = maxy;
1671  vertices[2].z = 0.0f;
1672  vertices[2].color = color;
1673  vertices[2].u = maxu;
1674  vertices[2].v = maxv;
1675 
1676  vertices[3].x = minx;
1677  vertices[3].y = maxy;
1678  vertices[3].z = 0.0f;
1679  vertices[3].color = color;
1680  vertices[3].u = minu;
1681  vertices[3].v = maxv;
1682 
1683  D3D_SetBlendMode(data, texture->blendMode);
1684 
1685  /* Rotate and translate */
1686  ID3DXMatrixStack_Push(data->matrixStack);
1687  ID3DXMatrixStack_LoadIdentity(data->matrixStack);
1688  ID3DXMatrixStack_RotateYawPitchRoll(data->matrixStack, 0.0, 0.0, (float)(M_PI * (float) angle / 180.0f));
1689  ID3DXMatrixStack_Translate(data->matrixStack, (float)dstrect->x + centerx, (float)dstrect->y + centery, (float)0.0);
1690  IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
1691 
1692  D3D_UpdateTextureScaleMode(data, texturedata, 0);
1693 
1694  result =
1696  texturedata->texture);
1697  if (FAILED(result)) {
1698  return D3D_SetError("SetTexture()", result);
1699  }
1700 
1701  if (texturedata->yuv) {
1702  shader = data->ps_yuv;
1703 
1704  D3D_UpdateTextureScaleMode(data, texturedata, 1);
1705  D3D_UpdateTextureScaleMode(data, texturedata, 2);
1706 
1707  result =
1709  texturedata->utexture);
1710  if (FAILED(result)) {
1711  return D3D_SetError("SetTexture()", result);
1712  }
1713 
1714  result =
1716  texturedata->vtexture);
1717  if (FAILED(result)) {
1718  return D3D_SetError("SetTexture()", result);
1719  }
1720  }
1721 
1722  if (shader) {
1723  result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1724  if (FAILED(result)) {
1725  return D3D_SetError("SetShader()", result);
1726  }
1727  }
1728  result =
1730  vertices, sizeof(*vertices));
1731  if (FAILED(result)) {
1732  return D3D_SetError("DrawPrimitiveUP()", result);
1733  }
1734  if (shader) {
1735  result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
1736  if (FAILED(result)) {
1737  return D3D_SetError("SetShader()", result);
1738  }
1739  }
1740  ID3DXMatrixStack_Pop(data->matrixStack);
1741  ID3DXMatrixStack_Push(data->matrixStack);
1742  ID3DXMatrixStack_LoadIdentity(data->matrixStack);
1743  IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
1744  ID3DXMatrixStack_Pop(data->matrixStack);
1745  return 0;
1746 }
1747 
1748 static int
1749 D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1750  Uint32 format, void * pixels, int pitch)
1751 {
1752  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1753  D3DSURFACE_DESC desc;
1754  LPDIRECT3DSURFACE9 backBuffer;
1756  RECT d3drect;
1757  D3DLOCKED_RECT locked;
1758  HRESULT result;
1759 
1760  result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
1761  if (FAILED(result)) {
1762  return D3D_SetError("GetBackBuffer()", result);
1763  }
1764 
1765  result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
1766  if (FAILED(result)) {
1767  IDirect3DSurface9_Release(backBuffer);
1768  return D3D_SetError("GetDesc()", result);
1769  }
1770 
1771  result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
1772  if (FAILED(result)) {
1773  IDirect3DSurface9_Release(backBuffer);
1774  return D3D_SetError("CreateOffscreenPlainSurface()", result);
1775  }
1776 
1777  result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
1778  if (FAILED(result)) {
1780  IDirect3DSurface9_Release(backBuffer);
1781  return D3D_SetError("GetRenderTargetData()", result);
1782  }
1783 
1784  d3drect.left = rect->x;
1785  d3drect.right = rect->x + rect->w;
1786  d3drect.top = rect->y;
1787  d3drect.bottom = rect->y + rect->h;
1788 
1789  result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
1790  if (FAILED(result)) {
1792  IDirect3DSurface9_Release(backBuffer);
1793  return D3D_SetError("LockRect()", result);
1794  }
1795 
1796  SDL_ConvertPixels(rect->w, rect->h,
1797  D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
1798  format, pixels, pitch);
1799 
1801 
1803  IDirect3DSurface9_Release(backBuffer);
1804 
1805  return 0;
1806 }
1807 
1808 static void
1809 D3D_RenderPresent(SDL_Renderer * renderer)
1810 {
1811  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1812  HRESULT result;
1813 
1814  if (!data->beginScene) {
1815  IDirect3DDevice9_EndScene(data->device);
1816  data->beginScene = SDL_TRUE;
1817  }
1818 
1819  result = IDirect3DDevice9_TestCooperativeLevel(data->device);
1820  if (result == D3DERR_DEVICELOST) {
1821  /* We'll reset later */
1822  return;
1823  }
1824  if (result == D3DERR_DEVICENOTRESET) {
1825  D3D_Reset(renderer);
1826  }
1827  result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
1828  if (FAILED(result)) {
1829  D3D_SetError("Present()", result);
1830  }
1831 }
1832 
1833 static void
1834 D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1835 {
1836  D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1837 
1838  if (!data) {
1839  return;
1840  }
1841  if (data->texture) {
1842  IDirect3DTexture9_Release(data->texture);
1843  }
1844  if (data->utexture) {
1845  IDirect3DTexture9_Release(data->utexture);
1846  }
1847  if (data->vtexture) {
1848  IDirect3DTexture9_Release(data->vtexture);
1849  }
1850  SDL_free(data->pixels);
1851  SDL_free(data);
1852  texture->driverdata = NULL;
1853 }
1854 
1855 static void
1856 D3D_DestroyRenderer(SDL_Renderer * renderer)
1857 {
1858  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1859 
1860  if (data) {
1861  /* Release the render target */
1862  if (data->defaultRenderTarget) {
1863  IDirect3DSurface9_Release(data->defaultRenderTarget);
1864  data->defaultRenderTarget = NULL;
1865  }
1866  if (data->currentRenderTarget != NULL) {
1867  IDirect3DSurface9_Release(data->currentRenderTarget);
1868  data->currentRenderTarget = NULL;
1869  }
1870  if (data->ps_yuv) {
1871  IDirect3DPixelShader9_Release(data->ps_yuv);
1872  }
1873  if (data->device) {
1874  IDirect3DDevice9_Release(data->device);
1875  }
1876  if (data->d3d) {
1877  IDirect3D9_Release(data->d3d);
1878  ID3DXMatrixStack_Release(data->matrixStack);
1879  SDL_UnloadObject(data->d3dDLL);
1880  }
1881  SDL_free(data);
1882  }
1883  SDL_free(renderer);
1884 }
1885 
1887 SDL_RenderGetD3D9Device(SDL_Renderer * renderer)
1888 {
1889  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1890  IDirect3DDevice9 *device;
1891 
1892  // Make sure that this is a D3D renderer
1893  if (renderer->DestroyRenderer != D3D_DestroyRenderer) {
1894  SDL_SetError("Renderer is not a D3D renderer");
1895  return NULL;
1896  }
1897 
1898  device = data->device;
1899  if (device) {
1900  IDirect3DDevice9_AddRef( device );
1901  }
1902  return device;
1903 }
1904 
1905 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
1906 
1907 /* vi: set ts=4 sw=4 expandtab: */
#define IDirect3DDevice9_SetTextureStageState(p, a, b, c)
Definition: d3d9.h:657
#define IDirect3D9_CreateDevice(p, a, b, c, d, e, f)
Definition: d3d9.h:380
int(* UpdateClipRect)(SDL_Renderer *renderer)
#define IDirect3DTexture9_UnlockRect(p, a)
Definition: d3d9.h:1239
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:57
#define IDirect3DSurface9_Release(p)
Definition: d3d9.h:1663
struct IDirect3D9 IDirect3D9
DECLSPEC SDL_bool SDLCALL SDL_GetWindowWMInfo(SDL_Window *window, SDL_SysWMinfo *info)
This function allows access to driver-dependent window information.
Definition: SDL_video.c:3002
#define D3DERR_DEVICELOST
Definition: d3d9.h:1997
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:42
#define D3DERR_OUTOFVIDEOMEMORY
Definition: d3d9.h:2000
struct _D3DVECTOR * LPD3DXVECTOR3
Definition: d3dx9math.h:199
#define IDirect3DDevice9_Clear(p, a, b, c, d, e, f)
Definition: d3d9.h:633
#define IDirect3DDevice9_GetBackBuffer(p, a, b, c, d)
Definition: d3d9.h:608
#define D3DERR_DRIVERINVALIDCALL
Definition: d3d9.h:2003
D3DSWAPEFFECT SwapEffect
Definition: d3d9types.h:1512
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
D3DFORMAT BackBufferFormat
Definition: d3d9types.h:1506
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:80
GLuint color
Definition: glew.h:7185
#define D3DLOCK_READONLY
Definition: d3d9types.h:1658
SDL_RendererInfo info
DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch)
Copy a block of pixels of one format to another format.
Definition: SDL_surface.c:984
#define NULL
Definition: ftobjs.h:61
#define IDirect3DTexture9_GetSurfaceLevel(p, a, b)
Definition: d3d9.h:1237
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
int(* RenderClear)(SDL_Renderer *renderer)
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:227
DWORD MaxTextureWidth
Definition: d3d9caps.h:155
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
DWORD Height
Definition: d3d9types.h:99
GLdouble angle
Definition: glew.h:8396
#define D3DCOLOR_ARGB(a, r, g, b)
Definition: d3d9types.h:37
#define D3DLOCK_DISCARD
Definition: d3d9types.h:1659
SDL_bool
Definition: SDL_stdinc.h:116
#define D3DERR_UNSUPPORTEDFACTORVALUE
Definition: d3d9.h:1989
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:82
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:118
#define IDirect3DTexture9_Release(p)
Definition: d3d9.h:1221
#define IDirect3DDevice9_SetViewport(p, a)
Definition: d3d9.h:637
HRESULT WINAPI D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO *pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER *ppShader, LPD3DXBUFFER *ppErrorMsgs)
DWORD PrimitiveMiscCaps
Definition: d3d9caps.h:139
#define IDirect3DPixelShader9_Release(p)
Definition: d3d9.h:1084
DWORD NumSimultaneousRTs
Definition: d3d9caps.h:205
void * driverdata
#define D3DERR_UNSUPPORTEDCOLORARG
Definition: d3d9.h:1984
EGLSurface EGLint x
Definition: eglext.h:293
EGLSurface surface
Definition: eglext.h:74
#define D3DERR_TOOMANYOPERATIONS
Definition: d3d9.h:1987
interface IDirect3DSwapChain9 IDirect3DSwapChain9
Definition: d3d9.h:271
DWORD MaxTextureHeight
Definition: d3d9caps.h:155
DECLSPEC void SDLCALL SDL_free(void *mem)
Uint32 texture_formats[16]
Definition: SDL_render.h:83
The structure that defines a display mode.
Definition: SDL_video.h:53
SDL_version version
Definition: SDL_syswm.h:161
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:123
#define D3DFVF_TEX1
Definition: d3d9types.h:673
DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h)
Get the size of a window&#39;s client area.
Definition: SDL_video.c:1638
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:99
#define IDirect3DDevice9_SetFVF(p, a)
Definition: d3d9.h:679
#define D3DERR_NOTAVAILABLE
Definition: d3d9.h:1999
#define D3DUSAGE_DYNAMIC
Definition: d3d9types.h:1582
SDL_Rect clip_rect
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
if(!yyg->yy_init)
DECLARE_INTERFACE_(IXAudio2, IUnknown)
Definition: XAudio2.h:425
#define IDirect3DDevice9_SetRenderTarget(p, a, b)
Definition: d3d9.h:627
DECLSPEC int SDLCALL SDL_GetWindowDisplayMode(SDL_Window *window, SDL_DisplayMode *mode)
Fill in information about the display mode used when a fullscreen window is visible.
Definition: SDL_video.c:1020
int max_texture_height
Definition: SDL_render.h:85
#define D3DFVF_DIFFUSE
Definition: d3d9types.h:667
#define IDirect3DDevice9_CreateOffscreenPlainSurface(p, a, b, c, d, e, f)
Definition: d3d9.h:626
#define IDirect3D9_Release(p)
Definition: d3d9.h:366
SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
Returns true if the rectangle has no area.
Definition: SDL_rect.h:72
#define D3DERR_UNSUPPORTEDTEXTUREFILTER
Definition: d3d9.h:1991
SDL_Window * window
#define D3DCREATE_SOFTWARE_VERTEXPROCESSING
Definition: d3d9.h:1834
SDL_RendererInfo info
interface IDirect3DSurface9 IDirect3DSurface9
Definition: d3d9.h:269
#define IDirect3DDevice9_SetScissorRect(p, a)
Definition: d3d9.h:665
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
struct IDirect3DPixelShader9 * LPDIRECT3DPIXELSHADER9
Definition: d3d9.h:1079
DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window)
Get the pixel format associated with the window.
Definition: SDL_video.c:1059
#define IDirect3DDevice9_Release(p)
Definition: d3d9.h:592
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:97
#define IDirect3DSwapChain9_Release(p)
Definition: d3d9.h:907
enum _D3DFORMAT D3DFORMAT
#define IDirect3DSwapChain9_GetPresentParameters(p, a)
Definition: d3d9.h:914
GLenum GLenum GLvoid * row
Definition: glew.h:4447
#define D3DUSAGE_RENDERTARGET
Definition: d3d9types.h:1580
#define D3DERR_CONFLICTINGTEXTUREPALETTE
Definition: d3d9.h:1992
ALuint u
Definition: alMain.h:58
int(* UpdateTextureYUV)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
Definition: SDL_sysrender.h:92
GLuint64EXT * result
Definition: glew.h:12708
GLuint shader
Definition: glew.h:1799
const GLdouble * v
Definition: glew.h:1377
#define IDirect3DDevice9_GetRenderTarget(p, a, b)
Definition: d3d9.h:628
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:89
GLenum GLenum dst
Definition: glew.h:2396
struct _D3DMATRIX * LPD3DXMATRIX
Definition: d3dx9math.h:359
#define D3DERR_CONFLICTINGTEXTUREFILTER
Definition: d3d9.h:1988
GLsizei GLsizei * length
Definition: gl2ext.h:792
#define IDirect3DDevice9_EndScene(p)
Definition: d3d9.h:632
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define IDirect3DDevice9_SetPixelShader(p, a)
Definition: d3d9.h:697
FT_Error error
Definition: cffdrivr.c:407
#define D3DCREATE_FPU_PRESERVE
Definition: d3d9.h:1830
float m[4][4]
Definition: d3d9types.h:89
static int GetScaleQuality(void)
#define D3DERR_DRIVERINTERNALERROR
Definition: d3d9.h:1993
#define IDirect3DDevice9_Reset(p, a)
Definition: d3d9.h:606
SDL_BlendMode blendMode
#define D3DPMISCCAPS_SEPARATEALPHABLEND
Definition: d3d9caps.h:322
#define D3DERR_WASSTILLDRAWING
Definition: d3d9.h:2004
GLint GLsizei count
Definition: gl2ext.h:1011
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define D3DERR_UNSUPPORTEDALPHAOPERATION
Definition: d3d9.h:1985
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
enum _D3DTEXTUREFILTERTYPE D3DTEXTUREFILTERTYPE
DECLSPEC void SDLCALL SDL_UnloadObject(void *handle)
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
interface ID3DXMatrixStack * LPD3DXMATRIXSTACK
Definition: d3dx9math.h:1304
GLuint index
Definition: glew.h:1800
#define D3DERR_UNSUPPORTEDALPHAARG
Definition: d3d9.h:1986
DECLSPEC int SDLCALL SDL_GetWindowDisplayIndex(SDL_Window *window)
Get the display index associated with a window.
Definition: SDL_video.c:936
#define FAR
Definition: zconf.h:215
#define IDirect3DDevice9_AddRef(p)
Definition: d3d9.h:591
DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window *window)
Get the window flags.
Definition: SDL_video.c:1409
int x
Definition: SDL_rect.h:65
#define D3DPRESENT_INTERVAL_ONE
Definition: d3d9caps.h:267
DECLSPEC const char *SDLCALL SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
#define D3DCREATE_MULTITHREADED
Definition: d3d9.h:1831
#define D3DERR_NOTFOUND
Definition: d3d9.h:1995
enum _D3DPOOL D3DPOOL
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define D3DERR_INVALIDDEVICE
Definition: d3d9.h:2001
#define FALSE
Definition: ftobjs.h:57
int w
Definition: SDL_rect.h:66
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
union SDL_SysWMinfo::@78 info
HRESULT WINAPI D3DXCreateMatrixStack(DWORD Flags, LPD3DXMATRIXSTACK *ppStack)
GLuint GLenum matrix
Definition: glew.h:13408
#define IDirect3DDevice9_SetTransform(p, a, b)
Definition: d3d9.h:634
static __inline ALuint minu(ALuint a, ALuint b)
Definition: alu.h:61
SDL_bool D3D_LoadDLL(void **pD3DDLL, IDirect3D9 **pDirect3D9Interface)
#define M_PI
Definition: os.h:45
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
#define D3DERR_WRONGTEXTUREFORMAT
Definition: d3d9.h:1982
#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE
A variable controlling whether the Direct3D device is initialized for thread-safe operations...
Definition: SDL_hints.h:106
typedef LPVOID(WINAPI *PFNWGLCREATEIMAGEBUFFERI3DPROC)(HDC hDC
Window state change event data (event.window.*)
Definition: SDL_events.h:160
#define IDirect3D9_GetDeviceCaps(p, a, b, c)
Definition: d3d9.h:378
GLuint GLfloat GLfloat GLfloat x1
Definition: glew.h:11582
DECLSPEC size_t SDLCALL SDL_strlen(const char *str)
Definition: SDL_string.c:389
#define IDirect3DDevice9_CreatePixelShader(p, a, b)
Definition: d3d9.h:696
#define D3D_OK
Definition: d3d9.h:1980
EGLSurface EGLint EGLint y
Definition: eglext.h:293
#define IDirect3DSurface9_GetDesc(p, a)
Definition: d3d9.h:1673
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
interface ID3DXMatrixStack ID3DXMatrixStack
Definition: d3dx9math.h:1303
#define IDirect3DDevice9_SetVertexShader(p, a)
Definition: d3d9.h:682
GLenum GLenum GLuint texture
Definition: gl2ext.h:850
#define D3DTS_WORLD
Definition: d3d9types.h:328
#define D3DDEVCAPS_HWTRANSFORMANDLIGHT
Definition: d3d9caps.h:296
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: gl2ext.h:845
#define IDirect3DDevice9_SetRenderState(p, a, b)
Definition: d3d9.h:647
#define D3DCLEAR_TARGET
Definition: d3d9types.h:189
#define D3DCREATE_HARDWARE_VERTEXPROCESSING
Definition: d3d9.h:1835
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
#define IDirect3DDevice9_SetTexture(p, a, b)
Definition: d3d9.h:655
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
#define IDirect3DDevice9_CreateTexture(p, a, b, c, d, e, f, g, h)
Definition: d3d9.h:613
DWORD DevCaps
Definition: d3d9caps.h:137
SDL_Rect viewport
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
int h
Definition: SDL_rect.h:66
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
DECLSPEC int SDLCALL SDL_atoi(const char *str)
Definition: SDL_string.c:774
#define IDirect3DDevice9_GetDeviceCaps(p, a)
Definition: d3d9.h:597
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
#define IDirect3DDevice9_GetRenderTargetData(p, a, b)
Definition: d3d9.h:622
#define IDirect3DDevice9_TestCooperativeLevel(p)
Definition: d3d9.h:593
GLfixed GLfixed x2
Definition: glext.h:4559
interface IDirect3DDevice9 IDirect3DDevice9
Definition: d3d9.h:257
DWORD MaxSimultaneousTextures
Definition: d3d9caps.h:174
interface IDirect3DTexture9 IDirect3DTexture9
Definition: d3d9.h:264
#define IDirect3DDevice9_GetSwapChain(p, a, b)
Definition: d3d9.h:604
#define D3DFVF_XYZ
Definition: d3d9types.h:656
#define D3DERR_UNSUPPORTEDCOLOROPERATION
Definition: d3d9.h:1983
GLdouble GLdouble GLdouble r
Definition: glew.h:1392
#define D3DERR_MOREDATA
Definition: d3d9.h:1996
GLint GLint GLint GLint z
Definition: gl2ext.h:1214
Uint32 num_texture_formats
Definition: SDL_render.h:82
interface ID3DXBuffer * LPD3DXBUFFER
Definition: d3dx9core.h:97
#define D3DERR_INVALIDCALL
Definition: d3d9.h:2002
Uint32 format
Definition: SDL_sysrender.h:52
#define IDirect3DSurface9_UnlockRect(p)
Definition: d3d9.h:1675
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
#define D3DERR_DEVICENOTRESET
Definition: d3d9.h:1998
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:226
void * driverdata
Definition: SDL_sysrender.h:69
int(* UpdateViewport)(SDL_Renderer *renderer)
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glew.h:3337
#define SDL_zero(x)
Definition: SDL_stdinc.h:254
#define IDirect3DTexture9_LockRect(p, a, b, c, d)
Definition: d3d9.h:1238
GLenum src
Definition: glew.h:2396
interface IDirect3DBaseTexture9 IDirect3DBaseTexture9
Definition: d3d9.h:263
Uint32 format
Definition: SDL_video.h:55
#define D3DPRESENT_INTERVAL_IMMEDIATE
Definition: d3d9caps.h:271
int i
Definition: pngrutil.c:1377
int(* RenderCopyEx)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
void(* RenderPresent)(SDL_Renderer *renderer)
DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle, const char *name)
#define D3DTA_DIFFUSE
Definition: d3d9types.h:615
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLfloat vertices[12]
Definition: modern.h:22
#define IDirect3DDevice9_Present(p, a, b, c, d)
Definition: d3d9.h:607
#define IDirect3DSurface9_LockRect(p, a, b, c)
Definition: d3d9.h:1674
struct IDirect3DSurface9 * LPDIRECT3DSURFACE9
Definition: d3d9.h:1658
GLsizeiptr const GLvoid GLenum usage
Definition: glew.h:1667
#define IDirect3DDevice9_DrawPrimitiveUP(p, a, b, c, d)
Definition: d3d9.h:673
#define IDirect3DDevice9_SetSamplerState(p, a, b, c)
Definition: d3d9.h:659
int y
Definition: SDL_rect.h:65
DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2)
Definition: SDL_string.c:946
#define TRUE
Definition: ftobjs.h:53
static __inline ALuint maxu(ALuint a, ALuint b)
Definition: alu.h:63
#define D3DTA_TEXTURE
Definition: d3d9types.h:617
DWORD Width
Definition: d3d9types.h:98
#define IDirect3DDevice9_BeginScene(p)
Definition: d3d9.h:631
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:63
interface ID3DXBuffer ID3DXBuffer
Definition: d3dx9core.h:96
cl_event event
Definition: glew.h:3556
#define D3DERR_CONFLICTINGRENDERSTATE
Definition: d3d9.h:1990