SDL  2.0
SDL_render_d3d.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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_internal.h"
22 
23 #include "SDL_render.h"
24 #include "SDL_system.h"
25 
26 #if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
27 
28 #include "../../core/windows/SDL_windows.h"
29 
30 #include "SDL_hints.h"
31 #include "SDL_loadso.h"
32 #include "SDL_syswm.h"
33 #include "../SDL_sysrender.h"
34 #include "../SDL_d3dmath.h"
35 #include "../../video/windows/SDL_windowsvideo.h"
36 
37 #if SDL_VIDEO_RENDER_D3D
38 #define D3D_DEBUG_INFO
39 #include <d3d9.h>
40 #endif
41 
42 #include "SDL_shaders_d3d.h"
43 
44 
45 /* Direct3D renderer implementation */
46 
47 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
48 static void D3D_WindowEvent(SDL_Renderer * renderer,
49  const SDL_WindowEvent *event);
50 static SDL_bool D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
51 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
52 static int D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
53 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
54  const SDL_Rect * rect, const void *pixels,
55  int pitch);
56 static int D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
57  const SDL_Rect * rect,
58  const Uint8 *Yplane, int Ypitch,
59  const Uint8 *Uplane, int Upitch,
60  const Uint8 *Vplane, int Vpitch);
61 static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
62  const SDL_Rect * rect, void **pixels, int *pitch);
63 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
64 static int D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture);
65 static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
66 static int D3D_UpdateViewport(SDL_Renderer * renderer);
67 static int D3D_UpdateClipRect(SDL_Renderer * renderer);
68 static int D3D_RenderClear(SDL_Renderer * renderer);
69 static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
70  const SDL_FPoint * points, int count);
71 static int D3D_RenderDrawLines(SDL_Renderer * renderer,
72  const SDL_FPoint * points, int count);
73 static int D3D_RenderFillRects(SDL_Renderer * renderer,
74  const SDL_FRect * rects, int count);
75 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
76  const SDL_Rect * srcrect, const SDL_FRect * dstrect);
77 static int D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
78  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
79  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
80 static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
81  Uint32 format, void * pixels, int pitch);
82 static void D3D_RenderPresent(SDL_Renderer * renderer);
83 static void D3D_DestroyTexture(SDL_Renderer * renderer,
85 static void D3D_DestroyRenderer(SDL_Renderer * renderer);
86 
87 
89  D3D_CreateRenderer,
90  {
91  "direct3d",
93  1,
95  0,
96  0}
97 };
98 
99 typedef struct
100 {
101  void* d3dDLL;
102  IDirect3D9 *d3d;
104  UINT adapter;
105  D3DPRESENT_PARAMETERS pparams;
106  SDL_bool updateSize;
107  SDL_bool beginScene;
108  SDL_bool enableSeparateAlphaBlend;
109  D3DTEXTUREFILTERTYPE scaleMode[8];
110  IDirect3DSurface9 *defaultRenderTarget;
111  IDirect3DSurface9 *currentRenderTarget;
112  void* d3dxDLL;
113  LPDIRECT3DPIXELSHADER9 shaders[NUM_SHADERS];
114 } D3D_RenderData;
115 
116 typedef struct
117 {
118  SDL_bool dirty;
119  int w, h;
120  DWORD usage;
121  Uint32 format;
122  D3DFORMAT d3dfmt;
123  IDirect3DTexture9 *texture;
124  IDirect3DTexture9 *staging;
125 } D3D_TextureRep;
126 
127 typedef struct
128 {
129  D3D_TextureRep texture;
130  D3DTEXTUREFILTERTYPE scaleMode;
131 
132  /* YV12 texture support */
133  SDL_bool yuv;
134  D3D_TextureRep utexture;
135  D3D_TextureRep vtexture;
136  Uint8 *pixels;
137  int pitch;
138  SDL_Rect locked_rect;
139 } D3D_TextureData;
140 
141 typedef struct
142 {
143  float x, y, z;
144  DWORD color;
145  float u, v;
146 } Vertex;
147 
148 static int
149 D3D_SetError(const char *prefix, HRESULT result)
150 {
151  const char *error;
152 
153  switch (result) {
154  case D3DERR_WRONGTEXTUREFORMAT:
155  error = "WRONGTEXTUREFORMAT";
156  break;
157  case D3DERR_UNSUPPORTEDCOLOROPERATION:
158  error = "UNSUPPORTEDCOLOROPERATION";
159  break;
160  case D3DERR_UNSUPPORTEDCOLORARG:
161  error = "UNSUPPORTEDCOLORARG";
162  break;
163  case D3DERR_UNSUPPORTEDALPHAOPERATION:
164  error = "UNSUPPORTEDALPHAOPERATION";
165  break;
166  case D3DERR_UNSUPPORTEDALPHAARG:
167  error = "UNSUPPORTEDALPHAARG";
168  break;
169  case D3DERR_TOOMANYOPERATIONS:
170  error = "TOOMANYOPERATIONS";
171  break;
172  case D3DERR_CONFLICTINGTEXTUREFILTER:
173  error = "CONFLICTINGTEXTUREFILTER";
174  break;
175  case D3DERR_UNSUPPORTEDFACTORVALUE:
176  error = "UNSUPPORTEDFACTORVALUE";
177  break;
178  case D3DERR_CONFLICTINGRENDERSTATE:
179  error = "CONFLICTINGRENDERSTATE";
180  break;
181  case D3DERR_UNSUPPORTEDTEXTUREFILTER:
182  error = "UNSUPPORTEDTEXTUREFILTER";
183  break;
184  case D3DERR_CONFLICTINGTEXTUREPALETTE:
185  error = "CONFLICTINGTEXTUREPALETTE";
186  break;
187  case D3DERR_DRIVERINTERNALERROR:
188  error = "DRIVERINTERNALERROR";
189  break;
190  case D3DERR_NOTFOUND:
191  error = "NOTFOUND";
192  break;
193  case D3DERR_MOREDATA:
194  error = "MOREDATA";
195  break;
196  case D3DERR_DEVICELOST:
197  error = "DEVICELOST";
198  break;
199  case D3DERR_DEVICENOTRESET:
200  error = "DEVICENOTRESET";
201  break;
202  case D3DERR_NOTAVAILABLE:
203  error = "NOTAVAILABLE";
204  break;
205  case D3DERR_OUTOFVIDEOMEMORY:
206  error = "OUTOFVIDEOMEMORY";
207  break;
208  case D3DERR_INVALIDDEVICE:
209  error = "INVALIDDEVICE";
210  break;
211  case D3DERR_INVALIDCALL:
212  error = "INVALIDCALL";
213  break;
214  case D3DERR_DRIVERINVALIDCALL:
215  error = "DRIVERINVALIDCALL";
216  break;
217  case D3DERR_WASSTILLDRAWING:
218  error = "WASSTILLDRAWING";
219  break;
220  default:
221  error = "UNKNOWN";
222  break;
223  }
224  return SDL_SetError("%s: %s", prefix, error);
225 }
226 
227 static D3DFORMAT
228 PixelFormatToD3DFMT(Uint32 format)
229 {
230  switch (format) {
232  return D3DFMT_R5G6B5;
234  return D3DFMT_X8R8G8B8;
236  return D3DFMT_A8R8G8B8;
241  return D3DFMT_L8;
242  default:
243  return D3DFMT_UNKNOWN;
244  }
245 }
246 
247 static Uint32
248 D3DFMTToPixelFormat(D3DFORMAT format)
249 {
250  switch (format) {
251  case D3DFMT_R5G6B5:
252  return SDL_PIXELFORMAT_RGB565;
253  case D3DFMT_X8R8G8B8:
254  return SDL_PIXELFORMAT_RGB888;
255  case D3DFMT_A8R8G8B8:
257  default:
259  }
260 }
261 
262 static void
263 D3D_InitRenderState(D3D_RenderData *data)
264 {
265  D3DMATRIX matrix;
266 
267  IDirect3DDevice9 *device = data->device;
268 
269  IDirect3DDevice9_SetVertexShader(device, NULL);
270  IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
271  IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
272  IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
273  IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
274 
275  /* Enable color modulation by diffuse color */
276  IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP,
277  D3DTOP_MODULATE);
278  IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1,
279  D3DTA_TEXTURE);
280  IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2,
281  D3DTA_DIFFUSE);
282 
283  /* Enable alpha modulation by diffuse alpha */
284  IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP,
285  D3DTOP_MODULATE);
286  IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1,
287  D3DTA_TEXTURE);
288  IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG2,
289  D3DTA_DIFFUSE);
290 
291  /* Enable separate alpha blend function, if possible */
292  if (data->enableSeparateAlphaBlend) {
293  IDirect3DDevice9_SetRenderState(device, D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
294  }
295 
296  /* Disable second texture stage, since we're done */
297  IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP,
298  D3DTOP_DISABLE);
299  IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP,
300  D3DTOP_DISABLE);
301 
302  /* Set an identity world and view matrix */
303  matrix.m[0][0] = 1.0f;
304  matrix.m[0][1] = 0.0f;
305  matrix.m[0][2] = 0.0f;
306  matrix.m[0][3] = 0.0f;
307  matrix.m[1][0] = 0.0f;
308  matrix.m[1][1] = 1.0f;
309  matrix.m[1][2] = 0.0f;
310  matrix.m[1][3] = 0.0f;
311  matrix.m[2][0] = 0.0f;
312  matrix.m[2][1] = 0.0f;
313  matrix.m[2][2] = 1.0f;
314  matrix.m[2][3] = 0.0f;
315  matrix.m[3][0] = 0.0f;
316  matrix.m[3][1] = 0.0f;
317  matrix.m[3][2] = 0.0f;
318  matrix.m[3][3] = 1.0f;
319  IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &matrix);
320  IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
321 
322  /* Reset our current scale mode */
323  SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
324 
325  /* Start the render with beginScene */
326  data->beginScene = SDL_TRUE;
327 }
328 
329 static int
330 D3D_Reset(SDL_Renderer * renderer)
331 {
332  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
333  HRESULT result;
335 
336  /* Release the default render target before reset */
337  if (data->defaultRenderTarget) {
338  IDirect3DSurface9_Release(data->defaultRenderTarget);
339  data->defaultRenderTarget = NULL;
340  }
341  if (data->currentRenderTarget != NULL) {
342  IDirect3DSurface9_Release(data->currentRenderTarget);
343  data->currentRenderTarget = NULL;
344  }
345 
346  /* Release application render targets */
347  for (texture = renderer->textures; texture; texture = texture->next) {
348  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
349  D3D_DestroyTexture(renderer, texture);
350  } else {
351  D3D_RecreateTexture(renderer, texture);
352  }
353  }
354 
355  result = IDirect3DDevice9_Reset(data->device, &data->pparams);
356  if (FAILED(result)) {
357  if (result == D3DERR_DEVICELOST) {
358  /* Don't worry about it, we'll reset later... */
359  return 0;
360  } else {
361  return D3D_SetError("Reset()", result);
362  }
363  }
364 
365  /* Allocate application render targets */
366  for (texture = renderer->textures; texture; texture = texture->next) {
367  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
368  D3D_CreateTexture(renderer, texture);
369  }
370  }
371 
372  IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
373  D3D_InitRenderState(data);
374  D3D_SetRenderTargetInternal(renderer, renderer->target);
375  D3D_UpdateViewport(renderer);
376 
377  /* Let the application know that render targets were reset */
378  {
380  event.type = SDL_RENDER_TARGETS_RESET;
381  SDL_PushEvent(&event);
382  }
383 
384  return 0;
385 }
386 
387 static int
388 D3D_ActivateRenderer(SDL_Renderer * renderer)
389 {
390  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
391  HRESULT result;
392 
393  if (data->updateSize) {
394  SDL_Window *window = renderer->window;
395  int w, h;
396  Uint32 window_flags = SDL_GetWindowFlags(window);
397 
398  SDL_GetWindowSize(window, &w, &h);
399  data->pparams.BackBufferWidth = w;
400  data->pparams.BackBufferHeight = h;
401  if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
402  SDL_DisplayMode fullscreen_mode;
403  SDL_GetWindowDisplayMode(window, &fullscreen_mode);
404  data->pparams.Windowed = FALSE;
405  data->pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
406  data->pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
407  } else {
408  data->pparams.Windowed = TRUE;
409  data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
410  data->pparams.FullScreen_RefreshRateInHz = 0;
411  }
412  if (D3D_Reset(renderer) < 0) {
413  return -1;
414  }
415 
416  data->updateSize = SDL_FALSE;
417  }
418  if (data->beginScene) {
419  result = IDirect3DDevice9_BeginScene(data->device);
420  if (result == D3DERR_DEVICELOST) {
421  if (D3D_Reset(renderer) < 0) {
422  return -1;
423  }
424  result = IDirect3DDevice9_BeginScene(data->device);
425  }
426  if (FAILED(result)) {
427  return D3D_SetError("BeginScene()", result);
428  }
429  data->beginScene = SDL_FALSE;
430  }
431  return 0;
432 }
433 
434 SDL_Renderer *
435 D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
436 {
438  D3D_RenderData *data;
439  SDL_SysWMinfo windowinfo;
440  HRESULT result;
441  D3DPRESENT_PARAMETERS pparams;
442  IDirect3DSwapChain9 *chain;
443  D3DCAPS9 caps;
444  DWORD device_flags;
445  Uint32 window_flags;
446  int w, h;
447  SDL_DisplayMode fullscreen_mode;
448  int displayIndex;
449 
450  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
451  if (!renderer) {
452  SDL_OutOfMemory();
453  return NULL;
454  }
455 
456  data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
457  if (!data) {
458  SDL_free(renderer);
459  SDL_OutOfMemory();
460  return NULL;
461  }
462 
463  if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) {
464  SDL_free(renderer);
465  SDL_free(data);
466  SDL_SetError("Unable to create Direct3D interface");
467  return NULL;
468  }
469 
470  renderer->WindowEvent = D3D_WindowEvent;
471  renderer->SupportsBlendMode = D3D_SupportsBlendMode;
472  renderer->CreateTexture = D3D_CreateTexture;
473  renderer->UpdateTexture = D3D_UpdateTexture;
474  renderer->UpdateTextureYUV = D3D_UpdateTextureYUV;
475  renderer->LockTexture = D3D_LockTexture;
476  renderer->UnlockTexture = D3D_UnlockTexture;
477  renderer->SetRenderTarget = D3D_SetRenderTarget;
478  renderer->UpdateViewport = D3D_UpdateViewport;
479  renderer->UpdateClipRect = D3D_UpdateClipRect;
480  renderer->RenderClear = D3D_RenderClear;
481  renderer->RenderDrawPoints = D3D_RenderDrawPoints;
482  renderer->RenderDrawLines = D3D_RenderDrawLines;
483  renderer->RenderFillRects = D3D_RenderFillRects;
484  renderer->RenderCopy = D3D_RenderCopy;
485  renderer->RenderCopyEx = D3D_RenderCopyEx;
486  renderer->RenderReadPixels = D3D_RenderReadPixels;
487  renderer->RenderPresent = D3D_RenderPresent;
488  renderer->DestroyTexture = D3D_DestroyTexture;
489  renderer->DestroyRenderer = D3D_DestroyRenderer;
490  renderer->info = D3D_RenderDriver.info;
492  renderer->driverdata = data;
493 
494  SDL_VERSION(&windowinfo.version);
495  SDL_GetWindowWMInfo(window, &windowinfo);
496 
497  window_flags = SDL_GetWindowFlags(window);
498  SDL_GetWindowSize(window, &w, &h);
499  SDL_GetWindowDisplayMode(window, &fullscreen_mode);
500 
501  SDL_zero(pparams);
502  pparams.hDeviceWindow = windowinfo.info.win.window;
503  pparams.BackBufferWidth = w;
504  pparams.BackBufferHeight = h;
505  pparams.BackBufferCount = 1;
506  pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
507 
508  if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
509  pparams.Windowed = FALSE;
510  pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format);
511  pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate;
512  } else {
513  pparams.Windowed = TRUE;
514  pparams.BackBufferFormat = D3DFMT_UNKNOWN;
515  pparams.FullScreen_RefreshRateInHz = 0;
516  }
517  if (flags & SDL_RENDERER_PRESENTVSYNC) {
518  pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
519  } else {
520  pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
521  }
522 
523  /* Get the adapter for the display that the window is on */
524  displayIndex = SDL_GetWindowDisplayIndex(window);
525  data->adapter = SDL_Direct3D9GetAdapterIndex(displayIndex);
526 
527  IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
528 
529  device_flags = D3DCREATE_FPU_PRESERVE;
530  if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
531  device_flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
532  } else {
533  device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
534  }
535 
537  device_flags |= D3DCREATE_MULTITHREADED;
538  }
539 
540  result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
541  D3DDEVTYPE_HAL,
542  pparams.hDeviceWindow,
543  device_flags,
544  &pparams, &data->device);
545  if (FAILED(result)) {
546  D3D_DestroyRenderer(renderer);
547  D3D_SetError("CreateDevice()", result);
548  return NULL;
549  }
550 
551  /* Get presentation parameters to fill info */
552  result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
553  if (FAILED(result)) {
554  D3D_DestroyRenderer(renderer);
555  D3D_SetError("GetSwapChain()", result);
556  return NULL;
557  }
558  result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
559  if (FAILED(result)) {
560  IDirect3DSwapChain9_Release(chain);
561  D3D_DestroyRenderer(renderer);
562  D3D_SetError("GetPresentParameters()", result);
563  return NULL;
564  }
565  IDirect3DSwapChain9_Release(chain);
566  if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
567  renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
568  }
569  data->pparams = pparams;
570 
571  IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
572  renderer->info.max_texture_width = caps.MaxTextureWidth;
573  renderer->info.max_texture_height = caps.MaxTextureHeight;
574  if (caps.NumSimultaneousRTs >= 2) {
576  }
577 
578  if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) {
579  data->enableSeparateAlphaBlend = SDL_TRUE;
580  }
581 
582  /* Store the default render target */
583  IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
584  data->currentRenderTarget = NULL;
585 
586  /* Set up parameters for rendering */
587  D3D_InitRenderState(data);
588 
589  if (caps.MaxSimultaneousTextures >= 3) {
590  int i;
591  for (i = 0; i < SDL_arraysize(data->shaders); ++i) {
592  result = D3D9_CreatePixelShader(data->device, (D3D9_Shader)i, &data->shaders[i]);
593  if (FAILED(result)) {
594  D3D_SetError("CreatePixelShader()", result);
595  }
596  }
597  if (data->shaders[SHADER_YUV_JPEG] && data->shaders[SHADER_YUV_BT601] && data->shaders[SHADER_YUV_BT709]) {
600  }
601  }
602  return renderer;
603 }
604 
605 static void
606 D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
607 {
608  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
609 
610  if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
611  data->updateSize = SDL_TRUE;
612  }
613 }
614 
615 static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
616 {
617  switch (factor) {
619  return D3DBLEND_ZERO;
620  case SDL_BLENDFACTOR_ONE:
621  return D3DBLEND_ONE;
623  return D3DBLEND_SRCCOLOR;
625  return D3DBLEND_INVSRCCOLOR;
627  return D3DBLEND_SRCALPHA;
629  return D3DBLEND_INVSRCALPHA;
631  return D3DBLEND_DESTCOLOR;
633  return D3DBLEND_INVDESTCOLOR;
635  return D3DBLEND_DESTALPHA;
637  return D3DBLEND_INVDESTALPHA;
638  default:
639  return (D3DBLEND)0;
640  }
641 }
642 
643 static SDL_bool
644 D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
645 {
646  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
647  SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
648  SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
649  SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
650  SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
651  SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
652  SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
653 
654  if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
655  !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) {
656  return SDL_FALSE;
657  }
658  if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) {
659  return SDL_FALSE;
660  }
661  if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) {
662  return SDL_FALSE;
663  }
664  return SDL_TRUE;
665 }
666 
667 static D3DTEXTUREFILTERTYPE
668 GetScaleQuality(void)
669 {
670  const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
671 
672  if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
673  return D3DTEXF_POINT;
674  } else /* if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) */ {
675  return D3DTEXF_LINEAR;
676  }
677 }
678 
679 static int
680 D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, D3DFORMAT d3dfmt, int w, int h)
681 {
682  HRESULT result;
683 
684  texture->dirty = SDL_FALSE;
685  texture->w = w;
686  texture->h = h;
687  texture->usage = usage;
688  texture->format = format;
689  texture->d3dfmt = d3dfmt;
690 
691  result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
692  PixelFormatToD3DFMT(format),
693  D3DPOOL_DEFAULT, &texture->texture, NULL);
694  if (FAILED(result)) {
695  return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
696  }
697  return 0;
698 }
699 
700 
701 static int
702 D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture)
703 {
704  HRESULT result;
705 
706  if (texture->staging == NULL) {
707  result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, 0,
708  texture->d3dfmt, D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
709  if (FAILED(result)) {
710  return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result);
711  }
712  }
713  return 0;
714 }
715 
716 static int
717 D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
718 {
719  HRESULT result;
720 
721  if (texture->dirty && texture->staging) {
722  if (!texture->texture) {
723  result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
724  PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL);
725  if (FAILED(result)) {
726  return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
727  }
728  }
729 
730  result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
731  if (FAILED(result)) {
732  return D3D_SetError("UpdateTexture()", result);
733  }
734  texture->dirty = SDL_FALSE;
735  }
736  result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
737  if (FAILED(result)) {
738  return D3D_SetError("SetTexture()", result);
739  }
740  return 0;
741 }
742 
743 static int
744 D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture)
745 {
746  if (texture->texture) {
747  IDirect3DTexture9_Release(texture->texture);
748  texture->texture = NULL;
749  }
750  if (texture->staging) {
751  IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
752  texture->dirty = SDL_TRUE;
753  }
754  return 0;
755 }
756 
757 static int
758 D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, int x, int y, int w, int h, const void *pixels, int pitch)
759 {
760  RECT d3drect;
761  D3DLOCKED_RECT locked;
762  const Uint8 *src;
763  Uint8 *dst;
764  int row, length;
765  HRESULT result;
766 
767  if (D3D_CreateStagingTexture(device, texture) < 0) {
768  return -1;
769  }
770 
771  d3drect.left = x;
772  d3drect.right = x + w;
773  d3drect.top = y;
774  d3drect.bottom = y + h;
775 
776  result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0);
777  if (FAILED(result)) {
778  return D3D_SetError("LockRect()", result);
779  }
780 
781  src = (const Uint8 *)pixels;
782  dst = (Uint8 *)locked.pBits;
783  length = w * SDL_BYTESPERPIXEL(texture->format);
784  if (length == pitch && length == locked.Pitch) {
785  SDL_memcpy(dst, src, length*h);
786  } else {
787  if (length > pitch) {
788  length = pitch;
789  }
790  if (length > locked.Pitch) {
791  length = locked.Pitch;
792  }
793  for (row = 0; row < h; ++row) {
794  SDL_memcpy(dst, src, length);
795  src += pitch;
796  dst += locked.Pitch;
797  }
798  }
799  result = IDirect3DTexture9_UnlockRect(texture->staging, 0);
800  if (FAILED(result)) {
801  return D3D_SetError("UnlockRect()", result);
802  }
803  texture->dirty = SDL_TRUE;
804 
805  return 0;
806 }
807 
808 static void
809 D3D_DestroyTextureRep(D3D_TextureRep *texture)
810 {
811  if (texture->texture) {
812  IDirect3DTexture9_Release(texture->texture);
813  texture->texture = NULL;
814  }
815  if (texture->staging) {
816  IDirect3DTexture9_Release(texture->staging);
817  texture->staging = NULL;
818  }
819 }
820 
821 static int
822 D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
823 {
824  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
825  D3D_TextureData *texturedata;
826  DWORD usage;
827 
828  texturedata = (D3D_TextureData *) SDL_calloc(1, sizeof(*texturedata));
829  if (!texturedata) {
830  return SDL_OutOfMemory();
831  }
832  texturedata->scaleMode = GetScaleQuality();
833 
834  texture->driverdata = texturedata;
835 
836  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
837  usage = D3DUSAGE_RENDERTARGET;
838  } else {
839  usage = 0;
840  }
841 
842  if (D3D_CreateTextureRep(data->device, &texturedata->texture, usage, texture->format, PixelFormatToD3DFMT(texture->format), texture->w, texture->h) < 0) {
843  return -1;
844  }
845 
846  if (texture->format == SDL_PIXELFORMAT_YV12 ||
847  texture->format == SDL_PIXELFORMAT_IYUV) {
848  texturedata->yuv = SDL_TRUE;
849 
850  if (D3D_CreateTextureRep(data->device, &texturedata->utexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), (texture->w + 1) / 2, (texture->h + 1) / 2) < 0) {
851  return -1;
852  }
853 
854  if (D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), (texture->w + 1) / 2, (texture->h + 1) / 2) < 0) {
855  return -1;
856  }
857  }
858  return 0;
859 }
860 
861 static int
862 D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
863 {
864  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
865  D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
866 
867  if (!texturedata) {
868  return 0;
869  }
870 
871  if (D3D_RecreateTextureRep(data->device, &texturedata->texture) < 0) {
872  return -1;
873  }
874 
875  if (texturedata->yuv) {
876  if (D3D_RecreateTextureRep(data->device, &texturedata->utexture) < 0) {
877  return -1;
878  }
879 
880  if (D3D_RecreateTextureRep(data->device, &texturedata->vtexture) < 0) {
881  return -1;
882  }
883  }
884  return 0;
885 }
886 
887 static int
888 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
889  const SDL_Rect * rect, const void *pixels, int pitch)
890 {
891  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
892  D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
893 
894  if (!texturedata) {
895  SDL_SetError("Texture is not currently available");
896  return -1;
897  }
898 
899  if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
900  return -1;
901  }
902 
903  if (texturedata->yuv) {
904  /* Skip to the correct offset into the next texture */
905  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
906 
907  if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2) < 0) {
908  return -1;
909  }
910 
911  /* Skip to the correct offset into the next texture */
912  pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
913  if (D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, rect->x / 2, (rect->y + 1) / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2) < 0) {
914  return -1;
915  }
916  }
917  return 0;
918 }
919 
920 static int
921 D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
922  const SDL_Rect * rect,
923  const Uint8 *Yplane, int Ypitch,
924  const Uint8 *Uplane, int Upitch,
925  const Uint8 *Vplane, int Vpitch)
926 {
927  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
928  D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
929 
930  if (!texturedata) {
931  SDL_SetError("Texture is not currently available");
932  return -1;
933  }
934 
935  if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
936  return -1;
937  }
938  if (D3D_UpdateTextureRep(data->device, &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch) < 0) {
939  return -1;
940  }
941  if (D3D_UpdateTextureRep(data->device, &texturedata->vtexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch) < 0) {
942  return -1;
943  }
944  return 0;
945 }
946 
947 static int
948 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
949  const SDL_Rect * rect, void **pixels, int *pitch)
950 {
951  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
952  D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
953  IDirect3DDevice9 *device = data->device;
954 
955  if (!texturedata) {
956  SDL_SetError("Texture is not currently available");
957  return -1;
958  }
959 
960  texturedata->locked_rect = *rect;
961 
962  if (texturedata->yuv) {
963  /* It's more efficient to upload directly... */
964  if (!texturedata->pixels) {
965  texturedata->pitch = texture->w;
966  texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2);
967  if (!texturedata->pixels) {
968  return SDL_OutOfMemory();
969  }
970  }
971  *pixels =
972  (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
973  rect->x * SDL_BYTESPERPIXEL(texture->format));
974  *pitch = texturedata->pitch;
975  } else {
976  RECT d3drect;
977  D3DLOCKED_RECT locked;
978  HRESULT result;
979 
980  if (D3D_CreateStagingTexture(device, &texturedata->texture) < 0) {
981  return -1;
982  }
983 
984  d3drect.left = rect->x;
985  d3drect.right = rect->x + rect->w;
986  d3drect.top = rect->y;
987  d3drect.bottom = rect->y + rect->h;
988 
989  result = IDirect3DTexture9_LockRect(texturedata->texture.staging, 0, &locked, &d3drect, 0);
990  if (FAILED(result)) {
991  return D3D_SetError("LockRect()", result);
992  }
993  *pixels = locked.pBits;
994  *pitch = locked.Pitch;
995  }
996  return 0;
997 }
998 
999 static void
1000 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1001 {
1002  /*D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;*/
1003  D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
1004 
1005  if (!texturedata) {
1006  return;
1007  }
1008 
1009  if (texturedata->yuv) {
1010  const SDL_Rect *rect = &texturedata->locked_rect;
1011  void *pixels =
1012  (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
1013  rect->x * SDL_BYTESPERPIXEL(texture->format));
1014  D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
1015  } else {
1016  IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
1017  texturedata->texture.dirty = SDL_TRUE;
1018  }
1019 }
1020 
1021 static int
1022 D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
1023 {
1024  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1025  D3D_TextureData *texturedata;
1026  D3D_TextureRep *texturerep;
1027  HRESULT result;
1028  IDirect3DDevice9 *device = data->device;
1029 
1030  /* Release the previous render target if it wasn't the default one */
1031  if (data->currentRenderTarget != NULL) {
1032  IDirect3DSurface9_Release(data->currentRenderTarget);
1033  data->currentRenderTarget = NULL;
1034  }
1035 
1036  if (texture == NULL) {
1037  IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
1038  return 0;
1039  }
1040 
1041  texturedata = (D3D_TextureData *)texture->driverdata;
1042  if (!texturedata) {
1043  SDL_SetError("Texture is not currently available");
1044  return -1;
1045  }
1046 
1047  /* Make sure the render target is updated if it was locked and written to */
1048  texturerep = &texturedata->texture;
1049  if (texturerep->dirty && texturerep->staging) {
1050  if (!texturerep->texture) {
1051  result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h, 1, texturerep->usage,
1052  PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL);
1053  if (FAILED(result)) {
1054  return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
1055  }
1056  }
1057 
1058  result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texturerep->staging, (IDirect3DBaseTexture9 *)texturerep->texture);
1059  if (FAILED(result)) {
1060  return D3D_SetError("UpdateTexture()", result);
1061  }
1062  texturerep->dirty = SDL_FALSE;
1063  }
1064 
1065  result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget);
1066  if(FAILED(result)) {
1067  return D3D_SetError("GetSurfaceLevel()", result);
1068  }
1069  result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget);
1070  if(FAILED(result)) {
1071  return D3D_SetError("SetRenderTarget()", result);
1072  }
1073 
1074  return 0;
1075 }
1076 
1077 static int
1078 D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1079 {
1080  if (D3D_ActivateRenderer(renderer) < 0) {
1081  return -1;
1082  }
1083 
1084  return D3D_SetRenderTargetInternal(renderer, texture);
1085 }
1086 
1087 static int
1088 D3D_UpdateViewport(SDL_Renderer * renderer)
1089 {
1090  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1091  D3DVIEWPORT9 viewport;
1092  D3DMATRIX matrix;
1093 
1094  /* Set the viewport */
1095  viewport.X = renderer->viewport.x;
1096  viewport.Y = renderer->viewport.y;
1097  viewport.Width = renderer->viewport.w;
1098  viewport.Height = renderer->viewport.h;
1099  viewport.MinZ = 0.0f;
1100  viewport.MaxZ = 1.0f;
1101  IDirect3DDevice9_SetViewport(data->device, &viewport);
1102 
1103  /* Set an orthographic projection matrix */
1104  if (renderer->viewport.w && renderer->viewport.h) {
1105  matrix.m[0][0] = 2.0f / renderer->viewport.w;
1106  matrix.m[0][1] = 0.0f;
1107  matrix.m[0][2] = 0.0f;
1108  matrix.m[0][3] = 0.0f;
1109  matrix.m[1][0] = 0.0f;
1110  matrix.m[1][1] = -2.0f / renderer->viewport.h;
1111  matrix.m[1][2] = 0.0f;
1112  matrix.m[1][3] = 0.0f;
1113  matrix.m[2][0] = 0.0f;
1114  matrix.m[2][1] = 0.0f;
1115  matrix.m[2][2] = 1.0f;
1116  matrix.m[2][3] = 0.0f;
1117  matrix.m[3][0] = -1.0f;
1118  matrix.m[3][1] = 1.0f;
1119  matrix.m[3][2] = 0.0f;
1120  matrix.m[3][3] = 1.0f;
1121  IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
1122  }
1123 
1124  return 0;
1125 }
1126 
1127 static int
1128 D3D_UpdateClipRect(SDL_Renderer * renderer)
1129 {
1130  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1131 
1132  if (renderer->clipping_enabled) {
1133  const SDL_Rect *rect = &renderer->clip_rect;
1134  RECT r;
1135  HRESULT result;
1136 
1137  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
1138  r.left = renderer->viewport.x + rect->x;
1139  r.top = renderer->viewport.y + rect->y;
1140  r.right = renderer->viewport.x + rect->x + rect->w;
1141  r.bottom = renderer->viewport.y + rect->y + rect->h;
1142 
1143  result = IDirect3DDevice9_SetScissorRect(data->device, &r);
1144  if (result != D3D_OK) {
1145  D3D_SetError("SetScissor()", result);
1146  return -1;
1147  }
1148  } else {
1149  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
1150  }
1151  return 0;
1152 }
1153 
1154 static int
1155 D3D_RenderClear(SDL_Renderer * renderer)
1156 {
1157  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1158  DWORD color;
1159  HRESULT result;
1160  int BackBufferWidth, BackBufferHeight;
1161 
1162  if (D3D_ActivateRenderer(renderer) < 0) {
1163  return -1;
1164  }
1165 
1166  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1167 
1168  if (renderer->target) {
1169  BackBufferWidth = renderer->target->w;
1170  BackBufferHeight = renderer->target->h;
1171  } else {
1172  BackBufferWidth = data->pparams.BackBufferWidth;
1173  BackBufferHeight = data->pparams.BackBufferHeight;
1174  }
1175 
1176  if (renderer->clipping_enabled) {
1177  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
1178  }
1179 
1180  /* Don't reset the viewport if we don't have to! */
1181  if (!renderer->viewport.x && !renderer->viewport.y &&
1182  renderer->viewport.w == BackBufferWidth &&
1183  renderer->viewport.h == BackBufferHeight) {
1184  result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
1185  } else {
1186  D3DVIEWPORT9 viewport;
1187 
1188  /* Clear is defined to clear the entire render target */
1189  viewport.X = 0;
1190  viewport.Y = 0;
1191  viewport.Width = BackBufferWidth;
1192  viewport.Height = BackBufferHeight;
1193  viewport.MinZ = 0.0f;
1194  viewport.MaxZ = 1.0f;
1195  IDirect3DDevice9_SetViewport(data->device, &viewport);
1196 
1197  result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
1198 
1199  /* Reset the viewport */
1200  viewport.X = renderer->viewport.x;
1201  viewport.Y = renderer->viewport.y;
1202  viewport.Width = renderer->viewport.w;
1203  viewport.Height = renderer->viewport.h;
1204  viewport.MinZ = 0.0f;
1205  viewport.MaxZ = 1.0f;
1206  IDirect3DDevice9_SetViewport(data->device, &viewport);
1207  }
1208 
1209  if (renderer->clipping_enabled) {
1210  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
1211  }
1212 
1213  if (FAILED(result)) {
1214  return D3D_SetError("Clear()", result);
1215  }
1216  return 0;
1217 }
1218 
1219 static void
1220 D3D_SetBlendMode(D3D_RenderData * data, SDL_BlendMode blendMode)
1221 {
1222  if (blendMode == SDL_BLENDMODE_NONE) {
1223  IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE);
1224  } else {
1225  IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, TRUE);
1226  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
1227  GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)));
1228  IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
1229  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
1230  if (data->enableSeparateAlphaBlend) {
1231  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
1232  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)));
1233  IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
1234  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
1235  }
1236  }
1237 }
1238 
1239 static int
1240 D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
1241  int count)
1242 {
1243  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1244  DWORD color;
1245  Vertex *vertices;
1246  int i;
1247  HRESULT result;
1248 
1249  if (D3D_ActivateRenderer(renderer) < 0) {
1250  return -1;
1251  }
1252 
1253  D3D_SetBlendMode(data, renderer->blendMode);
1254 
1255  result =
1256  IDirect3DDevice9_SetTexture(data->device, 0,
1257  (IDirect3DBaseTexture9 *) 0);
1258  if (FAILED(result)) {
1259  return D3D_SetError("SetTexture()", result);
1260  }
1261 
1262  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1263 
1264  vertices = SDL_stack_alloc(Vertex, count);
1265  for (i = 0; i < count; ++i) {
1266  vertices[i].x = points[i].x;
1267  vertices[i].y = points[i].y;
1268  vertices[i].z = 0.0f;
1269  vertices[i].color = color;
1270  vertices[i].u = 0.0f;
1271  vertices[i].v = 0.0f;
1272  }
1273  result =
1274  IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
1275  vertices, sizeof(*vertices));
1276  SDL_stack_free(vertices);
1277  if (FAILED(result)) {
1278  return D3D_SetError("DrawPrimitiveUP()", result);
1279  }
1280  return 0;
1281 }
1282 
1283 static int
1284 D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
1285  int count)
1286 {
1287  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1288  DWORD color;
1289  Vertex *vertices;
1290  int i;
1291  HRESULT result;
1292 
1293  if (D3D_ActivateRenderer(renderer) < 0) {
1294  return -1;
1295  }
1296 
1297  D3D_SetBlendMode(data, renderer->blendMode);
1298 
1299  result =
1300  IDirect3DDevice9_SetTexture(data->device, 0,
1301  (IDirect3DBaseTexture9 *) 0);
1302  if (FAILED(result)) {
1303  return D3D_SetError("SetTexture()", result);
1304  }
1305 
1306  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1307 
1308  vertices = SDL_stack_alloc(Vertex, count);
1309  for (i = 0; i < count; ++i) {
1310  vertices[i].x = points[i].x;
1311  vertices[i].y = points[i].y;
1312  vertices[i].z = 0.0f;
1313  vertices[i].color = color;
1314  vertices[i].u = 0.0f;
1315  vertices[i].v = 0.0f;
1316  }
1317  result =
1318  IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
1319  vertices, sizeof(*vertices));
1320 
1321  /* DirectX 9 has the same line rasterization semantics as GDI,
1322  so we need to close the endpoint of the line */
1323  if (count == 2 ||
1324  points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1325  vertices[0].x = points[count-1].x;
1326  vertices[0].y = points[count-1].y;
1327  result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
1328  }
1329 
1330  SDL_stack_free(vertices);
1331  if (FAILED(result)) {
1332  return D3D_SetError("DrawPrimitiveUP()", result);
1333  }
1334  return 0;
1335 }
1336 
1337 static int
1338 D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
1339  int count)
1340 {
1341  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1342  DWORD color;
1343  int i;
1344  float minx, miny, maxx, maxy;
1345  Vertex vertices[4];
1346  HRESULT result;
1347 
1348  if (D3D_ActivateRenderer(renderer) < 0) {
1349  return -1;
1350  }
1351 
1352  D3D_SetBlendMode(data, renderer->blendMode);
1353 
1354  result =
1355  IDirect3DDevice9_SetTexture(data->device, 0,
1356  (IDirect3DBaseTexture9 *) 0);
1357  if (FAILED(result)) {
1358  return D3D_SetError("SetTexture()", result);
1359  }
1360 
1361  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1362 
1363  for (i = 0; i < count; ++i) {
1364  const SDL_FRect *rect = &rects[i];
1365 
1366  minx = rect->x;
1367  miny = rect->y;
1368  maxx = rect->x + rect->w;
1369  maxy = rect->y + rect->h;
1370 
1371  vertices[0].x = minx;
1372  vertices[0].y = miny;
1373  vertices[0].z = 0.0f;
1374  vertices[0].color = color;
1375  vertices[0].u = 0.0f;
1376  vertices[0].v = 0.0f;
1377 
1378  vertices[1].x = maxx;
1379  vertices[1].y = miny;
1380  vertices[1].z = 0.0f;
1381  vertices[1].color = color;
1382  vertices[1].u = 0.0f;
1383  vertices[1].v = 0.0f;
1384 
1385  vertices[2].x = maxx;
1386  vertices[2].y = maxy;
1387  vertices[2].z = 0.0f;
1388  vertices[2].color = color;
1389  vertices[2].u = 0.0f;
1390  vertices[2].v = 0.0f;
1391 
1392  vertices[3].x = minx;
1393  vertices[3].y = maxy;
1394  vertices[3].z = 0.0f;
1395  vertices[3].color = color;
1396  vertices[3].u = 0.0f;
1397  vertices[3].v = 0.0f;
1398 
1399  result =
1400  IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
1401  2, vertices, sizeof(*vertices));
1402  if (FAILED(result)) {
1403  return D3D_SetError("DrawPrimitiveUP()", result);
1404  }
1405  }
1406  return 0;
1407 }
1408 
1409 static void
1410 D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
1411 {
1412  if (texturedata->scaleMode != data->scaleMode[index]) {
1413  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER,
1414  texturedata->scaleMode);
1415  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER,
1416  texturedata->scaleMode);
1417  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU,
1418  D3DTADDRESS_CLAMP);
1419  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV,
1420  D3DTADDRESS_CLAMP);
1421  data->scaleMode[index] = texturedata->scaleMode;
1422  }
1423 }
1424 
1425 static int
1426 D3D_RenderSetupTextureState(SDL_Renderer * renderer, SDL_Texture * texture, LPDIRECT3DPIXELSHADER9 *shader)
1427 {
1428  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1429  D3D_TextureData *texturedata;
1430 
1431  *shader = NULL;
1432 
1433  texturedata = (D3D_TextureData *)texture->driverdata;
1434  if (!texturedata) {
1435  SDL_SetError("Texture is not currently available");
1436  return -1;
1437  }
1438 
1439  D3D_UpdateTextureScaleMode(data, texturedata, 0);
1440 
1441  if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
1442  return -1;
1443  }
1444 
1445  if (texturedata->yuv) {
1446  switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
1448  *shader = data->shaders[SHADER_YUV_JPEG];
1449  break;
1451  *shader = data->shaders[SHADER_YUV_BT601];
1452  break;
1454  *shader = data->shaders[SHADER_YUV_BT709];
1455  break;
1456  default:
1457  return SDL_SetError("Unsupported YUV conversion mode");
1458  }
1459 
1460  D3D_UpdateTextureScaleMode(data, texturedata, 1);
1461  D3D_UpdateTextureScaleMode(data, texturedata, 2);
1462 
1463  if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
1464  return -1;
1465  }
1466  if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
1467  return -1;
1468  }
1469  }
1470  return 0;
1471 }
1472 
1473 static int
1474 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1475  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1476 {
1477  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1478  LPDIRECT3DPIXELSHADER9 shader;
1479  float minx, miny, maxx, maxy;
1480  float minu, maxu, minv, maxv;
1481  DWORD color;
1482  Vertex vertices[4];
1483  HRESULT result;
1484 
1485  if (D3D_ActivateRenderer(renderer) < 0) {
1486  return -1;
1487  }
1488 
1489  minx = dstrect->x - 0.5f;
1490  miny = dstrect->y - 0.5f;
1491  maxx = dstrect->x + dstrect->w - 0.5f;
1492  maxy = dstrect->y + dstrect->h - 0.5f;
1493 
1494  minu = (float) srcrect->x / texture->w;
1495  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1496  minv = (float) srcrect->y / texture->h;
1497  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1498 
1499  color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1500 
1501  vertices[0].x = minx;
1502  vertices[0].y = miny;
1503  vertices[0].z = 0.0f;
1504  vertices[0].color = color;
1505  vertices[0].u = minu;
1506  vertices[0].v = minv;
1507 
1508  vertices[1].x = maxx;
1509  vertices[1].y = miny;
1510  vertices[1].z = 0.0f;
1511  vertices[1].color = color;
1512  vertices[1].u = maxu;
1513  vertices[1].v = minv;
1514 
1515  vertices[2].x = maxx;
1516  vertices[2].y = maxy;
1517  vertices[2].z = 0.0f;
1518  vertices[2].color = color;
1519  vertices[2].u = maxu;
1520  vertices[2].v = maxv;
1521 
1522  vertices[3].x = minx;
1523  vertices[3].y = maxy;
1524  vertices[3].z = 0.0f;
1525  vertices[3].color = color;
1526  vertices[3].u = minu;
1527  vertices[3].v = maxv;
1528 
1529  D3D_SetBlendMode(data, texture->blendMode);
1530 
1531  if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) {
1532  return -1;
1533  }
1534 
1535  if (shader) {
1536  result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1537  if (FAILED(result)) {
1538  return D3D_SetError("SetShader()", result);
1539  }
1540  }
1541  result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
1542  vertices, sizeof(*vertices));
1543  if (FAILED(result)) {
1544  D3D_SetError("DrawPrimitiveUP()", result);
1545  }
1546  if (shader) {
1547  IDirect3DDevice9_SetPixelShader(data->device, NULL);
1548  }
1549  return FAILED(result) ? -1 : 0;
1550 }
1551 
1552 
1553 static int
1554 D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1555  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1556  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
1557 {
1558  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1559  LPDIRECT3DPIXELSHADER9 shader = NULL;
1560  float minx, miny, maxx, maxy;
1561  float minu, maxu, minv, maxv;
1562  float centerx, centery;
1563  DWORD color;
1564  Vertex vertices[4];
1565  Float4X4 modelMatrix;
1566  HRESULT result;
1567 
1568  if (D3D_ActivateRenderer(renderer) < 0) {
1569  return -1;
1570  }
1571 
1572  centerx = center->x;
1573  centery = center->y;
1574 
1575  minx = -centerx;
1576  maxx = dstrect->w - centerx;
1577  miny = -centery;
1578  maxy = dstrect->h - centery;
1579 
1580  minu = (float) srcrect->x / texture->w;
1581  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1582  minv = (float) srcrect->y / texture->h;
1583  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1584 
1585  if (flip & SDL_FLIP_HORIZONTAL) {
1586  float tmp = maxu;
1587  maxu = minu;
1588  minu = tmp;
1589  }
1590  if (flip & SDL_FLIP_VERTICAL) {
1591  float tmp = maxv;
1592  maxv = minv;
1593  minv = tmp;
1594  }
1595 
1596  color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1597 
1598  vertices[0].x = minx;
1599  vertices[0].y = miny;
1600  vertices[0].z = 0.0f;
1601  vertices[0].color = color;
1602  vertices[0].u = minu;
1603  vertices[0].v = minv;
1604 
1605  vertices[1].x = maxx;
1606  vertices[1].y = miny;
1607  vertices[1].z = 0.0f;
1608  vertices[1].color = color;
1609  vertices[1].u = maxu;
1610  vertices[1].v = minv;
1611 
1612  vertices[2].x = maxx;
1613  vertices[2].y = maxy;
1614  vertices[2].z = 0.0f;
1615  vertices[2].color = color;
1616  vertices[2].u = maxu;
1617  vertices[2].v = maxv;
1618 
1619  vertices[3].x = minx;
1620  vertices[3].y = maxy;
1621  vertices[3].z = 0.0f;
1622  vertices[3].color = color;
1623  vertices[3].u = minu;
1624  vertices[3].v = maxv;
1625 
1626  D3D_SetBlendMode(data, texture->blendMode);
1627 
1628  if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) {
1629  return -1;
1630  }
1631 
1632  /* Rotate and translate */
1633  modelMatrix = MatrixMultiply(
1634  MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
1635  MatrixTranslation(dstrect->x + center->x - 0.5f, dstrect->y + center->y - 0.5f, 0));
1636  IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
1637 
1638  if (shader) {
1639  result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1640  if (FAILED(result)) {
1641  D3D_SetError("SetShader()", result);
1642  goto done;
1643  }
1644  }
1645  result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
1646  vertices, sizeof(*vertices));
1647  if (FAILED(result)) {
1648  D3D_SetError("DrawPrimitiveUP()", result);
1649  }
1650 done:
1651  if (shader) {
1652  IDirect3DDevice9_SetPixelShader(data->device, NULL);
1653  }
1654 
1655  modelMatrix = MatrixIdentity();
1656  IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
1657 
1658  return FAILED(result) ? -1 : 0;
1659 }
1660 
1661 static int
1662 D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1663  Uint32 format, void * pixels, int pitch)
1664 {
1665  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1666  D3DSURFACE_DESC desc;
1667  LPDIRECT3DSURFACE9 backBuffer;
1668  LPDIRECT3DSURFACE9 surface;
1669  RECT d3drect;
1670  D3DLOCKED_RECT locked;
1671  HRESULT result;
1672 
1673  if (data->currentRenderTarget) {
1674  backBuffer = data->currentRenderTarget;
1675  } else {
1676  backBuffer = data->defaultRenderTarget;
1677  }
1678 
1679  result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
1680  if (FAILED(result)) {
1681  IDirect3DSurface9_Release(backBuffer);
1682  return D3D_SetError("GetDesc()", result);
1683  }
1684 
1685  result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
1686  if (FAILED(result)) {
1687  IDirect3DSurface9_Release(backBuffer);
1688  return D3D_SetError("CreateOffscreenPlainSurface()", result);
1689  }
1690 
1691  result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
1692  if (FAILED(result)) {
1693  IDirect3DSurface9_Release(surface);
1694  IDirect3DSurface9_Release(backBuffer);
1695  return D3D_SetError("GetRenderTargetData()", result);
1696  }
1697 
1698  d3drect.left = rect->x;
1699  d3drect.right = rect->x + rect->w;
1700  d3drect.top = rect->y;
1701  d3drect.bottom = rect->y + rect->h;
1702 
1703  result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
1704  if (FAILED(result)) {
1705  IDirect3DSurface9_Release(surface);
1706  IDirect3DSurface9_Release(backBuffer);
1707  return D3D_SetError("LockRect()", result);
1708  }
1709 
1710  SDL_ConvertPixels(rect->w, rect->h,
1711  D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
1712  format, pixels, pitch);
1713 
1714  IDirect3DSurface9_UnlockRect(surface);
1715 
1716  IDirect3DSurface9_Release(surface);
1717 
1718  return 0;
1719 }
1720 
1721 static void
1722 D3D_RenderPresent(SDL_Renderer * renderer)
1723 {
1724  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1725  HRESULT result;
1726 
1727  if (!data->beginScene) {
1728  IDirect3DDevice9_EndScene(data->device);
1729  data->beginScene = SDL_TRUE;
1730  }
1731 
1732  result = IDirect3DDevice9_TestCooperativeLevel(data->device);
1733  if (result == D3DERR_DEVICELOST) {
1734  /* We'll reset later */
1735  return;
1736  }
1737  if (result == D3DERR_DEVICENOTRESET) {
1738  D3D_Reset(renderer);
1739  }
1740  result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
1741  if (FAILED(result)) {
1742  D3D_SetError("Present()", result);
1743  }
1744 }
1745 
1746 static void
1747 D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1748 {
1749  D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1750 
1751  if (!data) {
1752  return;
1753  }
1754  D3D_DestroyTextureRep(&data->texture);
1755  D3D_DestroyTextureRep(&data->utexture);
1756  D3D_DestroyTextureRep(&data->vtexture);
1757  SDL_free(data->pixels);
1758  SDL_free(data);
1759  texture->driverdata = NULL;
1760 }
1761 
1762 static void
1763 D3D_DestroyRenderer(SDL_Renderer * renderer)
1764 {
1765  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1766 
1767  if (data) {
1768  int i;
1769 
1770  /* Release the render target */
1771  if (data->defaultRenderTarget) {
1772  IDirect3DSurface9_Release(data->defaultRenderTarget);
1773  data->defaultRenderTarget = NULL;
1774  }
1775  if (data->currentRenderTarget != NULL) {
1776  IDirect3DSurface9_Release(data->currentRenderTarget);
1777  data->currentRenderTarget = NULL;
1778  }
1779  for (i = 0; i < SDL_arraysize(data->shaders); ++i) {
1780  if (data->shaders[i]) {
1781  IDirect3DPixelShader9_Release(data->shaders[i]);
1782  data->shaders[i] = NULL;
1783  }
1784  }
1785  if (data->device) {
1786  IDirect3DDevice9_Release(data->device);
1787  data->device = NULL;
1788  }
1789  if (data->d3d) {
1790  IDirect3D9_Release(data->d3d);
1791  SDL_UnloadObject(data->d3dDLL);
1792  }
1793  SDL_free(data);
1794  }
1795  SDL_free(renderer);
1796 }
1797 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
1798 
1799 #ifdef __WIN32__
1800 /* This function needs to always exist on Windows, for the Dynamic API. */
1803 {
1804  IDirect3DDevice9 *device = NULL;
1805 
1806 #if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
1807  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1808 
1809  /* Make sure that this is a D3D renderer */
1810  if (renderer->DestroyRenderer != D3D_DestroyRenderer) {
1811  SDL_SetError("Renderer is not a D3D renderer");
1812  return NULL;
1813  }
1814 
1815  device = data->device;
1816  if (device) {
1817  IDirect3DDevice9_AddRef(device);
1818  }
1819 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
1820 
1821  return device;
1822 }
1823 #endif /* __WIN32__ */
1824 
1825 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2193
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:75
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
GLuint GLenum matrix
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:57
struct IDirect3D9 IDirect3D9
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:98
#define SDL_GetWindowDisplayIndex
HRESULT D3D9_CreatePixelShader(IDirect3DDevice9 *d3dDevice, D3D9_Shader shader, IDirect3DPixelShader9 **pixelShader)
GLdouble GLdouble z
GLuint64EXT * result
GLuint sampler
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
const GLdouble * v
Definition: SDL_opengl.h:2064
SDL_RendererInfo info
GLenum GLenum dst
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_sysrender.h:82
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:143
GLfloat GLfloat GLfloat GLfloat h
void * driverdata
EGLSurface surface
Definition: eglext.h:248
Uint32 texture_formats[16]
Definition: SDL_render.h:83
The structure that defines a display mode.
Definition: SDL_video.h:53
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2221
#define SDL_GetHint
#define SDL_GetWindowFlags
SDL_version version
Definition: SDL_syswm.h:196
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2207
D3D9_Shader
GLfloat f
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
GLsizei GLsizei GLuint * shaders
SDL_Rect clip_rect
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define SDL_strcasecmp
GLenum src
SDL_Texture * textures
#define SDL_UnloadObject
int max_texture_height
Definition: SDL_render.h:85
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
Definition: SDL_blendmode.h:62
SDL_Window * window
SDL_RendererInfo info
int(* RenderClear)(SDL_Renderer *renderer)
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLfixed GLfixed GLint GLint GLfixed points
#define SDL_GetHintBoolean
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
int SDL_Direct3D9GetAdapterIndex(int displayIndex)
Returns the D3D9 adapter index that matches the specified display index.
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:90
static SDL_AudioDeviceID device
Definition: loopwave.c:37
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:93
#define SDL_GetWindowSize
#define FAILED(x)
Definition: SDL_directx.h:54
SDL_Texture * next
Definition: SDL_sysrender.h:72
#define SDL_memcpy
GLsizeiptr const void GLenum usage
GLenum GLenum GLuint texture
#define SDL_GetWindowDisplayMode
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2228
SDL_Texture * target
static int GetScaleQuality(void)
static SDL_Renderer * renderer
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
struct _cl_event * event
SDL_BlendMode blendMode
#define TRUE
Definition: edid-parse.c:33
int done
Definition: checkkeys.c:28
#define SDL_PushEvent
GLubyte GLubyte GLubyte GLubyte w
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int x
Definition: SDL_rect.h:66
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* UpdateViewport)(SDL_Renderer *renderer)
SDL_RenderDriver D3D_RenderDriver
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
int w
Definition: SDL_rect.h:67
GLuint index
SDL_bool D3D_LoadDLL(void **pD3DDLL, IDirect3D9 **pDirect3D9Interface)
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE
A variable controlling whether the Direct3D device is initialized for thread-safe operations...
Definition: SDL_hints.h:107
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Window state change event data (event.window.*)
Definition: SDL_events.h:174
#define SDL_GetWindowWMInfo
Window window
Definition: SDL_syswm.h:218
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2214
#define SDL_SetError
GLbitfield flags
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)
#define SDL_calloc
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_Rect viewport
int h
Definition: SDL_rect.h:67
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_Rect viewport
Definition: testviewport.c:28
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2200
GLuint color
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:80
GLfloat angle
Uint32 num_texture_formats
Definition: SDL_render.h:82
Uint32 format
Definition: SDL_sysrender.h:52
union SDL_SysWMinfo::@18 info
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
void * driverdata
Definition: SDL_sysrender.h:69
General event structure.
Definition: SDL_events.h:525
#define SDL_malloc
#define SDL_ConvertPixels
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:83
void(* RenderPresent)(SDL_Renderer *renderer)
Uint32 format
Definition: SDL_video.h:55
EGLSurface EGLint * rects
Definition: eglext.h:282
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
#define SDL_GetYUVConversionModeForResolution
GLuint GLsizei GLsizei * length
#define FALSE
Definition: edid-parse.c:34
int(* UpdateClipRect)(SDL_Renderer *renderer)
GLenum GLenum void * row
int y
Definition: SDL_rect.h:66
IDirect3DDevice9 * SDL_RenderGetD3D9Device(SDL_Renderer *renderer)
Returns the D3D device associated with a renderer, or NULL if it&#39;s not a D3D renderer.
SDL_bool clipping_enabled
#define SDL_memset
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
GLuint shader
struct IDirect3DDevice9 IDirect3DDevice9
Definition: SDL_system.h:60