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 
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 int
668 D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, D3DFORMAT d3dfmt, int w, int h)
669 {
670  HRESULT result;
671 
672  texture->dirty = SDL_FALSE;
673  texture->w = w;
674  texture->h = h;
675  texture->usage = usage;
676  texture->format = format;
677  texture->d3dfmt = d3dfmt;
678 
679  result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
680  PixelFormatToD3DFMT(format),
681  D3DPOOL_DEFAULT, &texture->texture, NULL);
682  if (FAILED(result)) {
683  return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
684  }
685  return 0;
686 }
687 
688 
689 static int
690 D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture)
691 {
692  HRESULT result;
693 
694  if (texture->staging == NULL) {
695  result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, 0,
696  texture->d3dfmt, D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
697  if (FAILED(result)) {
698  return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result);
699  }
700  }
701  return 0;
702 }
703 
704 static int
705 D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD sampler)
706 {
707  HRESULT result;
708 
709  if (texture->dirty && texture->staging) {
710  if (!texture->texture) {
711  result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
712  PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL);
713  if (FAILED(result)) {
714  return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
715  }
716  }
717 
718  result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture->staging, (IDirect3DBaseTexture9 *)texture->texture);
719  if (FAILED(result)) {
720  return D3D_SetError("UpdateTexture()", result);
721  }
722  texture->dirty = SDL_FALSE;
723  }
724  result = IDirect3DDevice9_SetTexture(device, sampler, (IDirect3DBaseTexture9 *)texture->texture);
725  if (FAILED(result)) {
726  return D3D_SetError("SetTexture()", result);
727  }
728  return 0;
729 }
730 
731 static int
732 D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture)
733 {
734  if (texture->texture) {
735  IDirect3DTexture9_Release(texture->texture);
736  texture->texture = NULL;
737  }
738  if (texture->staging) {
739  IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
740  texture->dirty = SDL_TRUE;
741  }
742  return 0;
743 }
744 
745 static int
746 D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, int x, int y, int w, int h, const void *pixels, int pitch)
747 {
748  RECT d3drect;
749  D3DLOCKED_RECT locked;
750  const Uint8 *src;
751  Uint8 *dst;
752  int row, length;
753  HRESULT result;
754 
755  if (D3D_CreateStagingTexture(device, texture) < 0) {
756  return -1;
757  }
758 
759  d3drect.left = x;
760  d3drect.right = x + w;
761  d3drect.top = y;
762  d3drect.bottom = y + h;
763 
764  result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0);
765  if (FAILED(result)) {
766  return D3D_SetError("LockRect()", result);
767  }
768 
769  src = (const Uint8 *)pixels;
770  dst = (Uint8 *)locked.pBits;
771  length = w * SDL_BYTESPERPIXEL(texture->format);
772  if (length == pitch && length == locked.Pitch) {
773  SDL_memcpy(dst, src, length*h);
774  } else {
775  if (length > pitch) {
776  length = pitch;
777  }
778  if (length > locked.Pitch) {
779  length = locked.Pitch;
780  }
781  for (row = 0; row < h; ++row) {
782  SDL_memcpy(dst, src, length);
783  src += pitch;
784  dst += locked.Pitch;
785  }
786  }
787  result = IDirect3DTexture9_UnlockRect(texture->staging, 0);
788  if (FAILED(result)) {
789  return D3D_SetError("UnlockRect()", result);
790  }
791  texture->dirty = SDL_TRUE;
792 
793  return 0;
794 }
795 
796 static void
797 D3D_DestroyTextureRep(D3D_TextureRep *texture)
798 {
799  if (texture->texture) {
800  IDirect3DTexture9_Release(texture->texture);
801  texture->texture = NULL;
802  }
803  if (texture->staging) {
804  IDirect3DTexture9_Release(texture->staging);
805  texture->staging = NULL;
806  }
807 }
808 
809 static int
810 D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
811 {
812  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
813  D3D_TextureData *texturedata;
814  DWORD usage;
815 
816  texturedata = (D3D_TextureData *) SDL_calloc(1, sizeof(*texturedata));
817  if (!texturedata) {
818  return SDL_OutOfMemory();
819  }
820  texturedata->scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
821 
822  texture->driverdata = texturedata;
823 
824  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
825  usage = D3DUSAGE_RENDERTARGET;
826  } else {
827  usage = 0;
828  }
829 
830  if (D3D_CreateTextureRep(data->device, &texturedata->texture, usage, texture->format, PixelFormatToD3DFMT(texture->format), texture->w, texture->h) < 0) {
831  return -1;
832  }
833 
834  if (texture->format == SDL_PIXELFORMAT_YV12 ||
835  texture->format == SDL_PIXELFORMAT_IYUV) {
836  texturedata->yuv = SDL_TRUE;
837 
838  if (D3D_CreateTextureRep(data->device, &texturedata->utexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), (texture->w + 1) / 2, (texture->h + 1) / 2) < 0) {
839  return -1;
840  }
841 
842  if (D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), (texture->w + 1) / 2, (texture->h + 1) / 2) < 0) {
843  return -1;
844  }
845  }
846  return 0;
847 }
848 
849 static int
850 D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
851 {
852  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
853  D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
854 
855  if (!texturedata) {
856  return 0;
857  }
858 
859  if (D3D_RecreateTextureRep(data->device, &texturedata->texture) < 0) {
860  return -1;
861  }
862 
863  if (texturedata->yuv) {
864  if (D3D_RecreateTextureRep(data->device, &texturedata->utexture) < 0) {
865  return -1;
866  }
867 
868  if (D3D_RecreateTextureRep(data->device, &texturedata->vtexture) < 0) {
869  return -1;
870  }
871  }
872  return 0;
873 }
874 
875 static int
876 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
877  const SDL_Rect * rect, const void *pixels, int pitch)
878 {
879  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
880  D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
881 
882  if (!texturedata) {
883  SDL_SetError("Texture is not currently available");
884  return -1;
885  }
886 
887  if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
888  return -1;
889  }
890 
891  if (texturedata->yuv) {
892  /* Skip to the correct offset into the next texture */
893  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
894 
895  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) {
896  return -1;
897  }
898 
899  /* Skip to the correct offset into the next texture */
900  pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
901  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) {
902  return -1;
903  }
904  }
905  return 0;
906 }
907 
908 static int
909 D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
910  const SDL_Rect * rect,
911  const Uint8 *Yplane, int Ypitch,
912  const Uint8 *Uplane, int Upitch,
913  const Uint8 *Vplane, int Vpitch)
914 {
915  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
916  D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
917 
918  if (!texturedata) {
919  SDL_SetError("Texture is not currently available");
920  return -1;
921  }
922 
923  if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
924  return -1;
925  }
926  if (D3D_UpdateTextureRep(data->device, &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch) < 0) {
927  return -1;
928  }
929  if (D3D_UpdateTextureRep(data->device, &texturedata->vtexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch) < 0) {
930  return -1;
931  }
932  return 0;
933 }
934 
935 static int
936 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
937  const SDL_Rect * rect, void **pixels, int *pitch)
938 {
939  D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
940  D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
941  IDirect3DDevice9 *device = data->device;
942 
943  if (!texturedata) {
944  SDL_SetError("Texture is not currently available");
945  return -1;
946  }
947 
948  texturedata->locked_rect = *rect;
949 
950  if (texturedata->yuv) {
951  /* It's more efficient to upload directly... */
952  if (!texturedata->pixels) {
953  texturedata->pitch = texture->w;
954  texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2);
955  if (!texturedata->pixels) {
956  return SDL_OutOfMemory();
957  }
958  }
959  *pixels =
960  (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
961  rect->x * SDL_BYTESPERPIXEL(texture->format));
962  *pitch = texturedata->pitch;
963  } else {
964  RECT d3drect;
965  D3DLOCKED_RECT locked;
966  HRESULT result;
967 
968  if (D3D_CreateStagingTexture(device, &texturedata->texture) < 0) {
969  return -1;
970  }
971 
972  d3drect.left = rect->x;
973  d3drect.right = rect->x + rect->w;
974  d3drect.top = rect->y;
975  d3drect.bottom = rect->y + rect->h;
976 
977  result = IDirect3DTexture9_LockRect(texturedata->texture.staging, 0, &locked, &d3drect, 0);
978  if (FAILED(result)) {
979  return D3D_SetError("LockRect()", result);
980  }
981  *pixels = locked.pBits;
982  *pitch = locked.Pitch;
983  }
984  return 0;
985 }
986 
987 static void
988 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
989 {
990  /*D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;*/
991  D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
992 
993  if (!texturedata) {
994  return;
995  }
996 
997  if (texturedata->yuv) {
998  const SDL_Rect *rect = &texturedata->locked_rect;
999  void *pixels =
1000  (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
1001  rect->x * SDL_BYTESPERPIXEL(texture->format));
1002  D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
1003  } else {
1004  IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
1005  texturedata->texture.dirty = SDL_TRUE;
1006  }
1007 }
1008 
1009 static int
1010 D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
1011 {
1012  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1013  D3D_TextureData *texturedata;
1014  D3D_TextureRep *texturerep;
1015  HRESULT result;
1016  IDirect3DDevice9 *device = data->device;
1017 
1018  /* Release the previous render target if it wasn't the default one */
1019  if (data->currentRenderTarget != NULL) {
1020  IDirect3DSurface9_Release(data->currentRenderTarget);
1021  data->currentRenderTarget = NULL;
1022  }
1023 
1024  if (texture == NULL) {
1025  IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
1026  return 0;
1027  }
1028 
1029  texturedata = (D3D_TextureData *)texture->driverdata;
1030  if (!texturedata) {
1031  SDL_SetError("Texture is not currently available");
1032  return -1;
1033  }
1034 
1035  /* Make sure the render target is updated if it was locked and written to */
1036  texturerep = &texturedata->texture;
1037  if (texturerep->dirty && texturerep->staging) {
1038  if (!texturerep->texture) {
1039  result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h, 1, texturerep->usage,
1040  PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL);
1041  if (FAILED(result)) {
1042  return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
1043  }
1044  }
1045 
1046  result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texturerep->staging, (IDirect3DBaseTexture9 *)texturerep->texture);
1047  if (FAILED(result)) {
1048  return D3D_SetError("UpdateTexture()", result);
1049  }
1050  texturerep->dirty = SDL_FALSE;
1051  }
1052 
1053  result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget);
1054  if(FAILED(result)) {
1055  return D3D_SetError("GetSurfaceLevel()", result);
1056  }
1057  result = IDirect3DDevice9_SetRenderTarget(data->device, 0, data->currentRenderTarget);
1058  if(FAILED(result)) {
1059  return D3D_SetError("SetRenderTarget()", result);
1060  }
1061 
1062  return 0;
1063 }
1064 
1065 static int
1066 D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1067 {
1068  if (D3D_ActivateRenderer(renderer) < 0) {
1069  return -1;
1070  }
1071 
1072  return D3D_SetRenderTargetInternal(renderer, texture);
1073 }
1074 
1075 static int
1076 D3D_UpdateViewport(SDL_Renderer * renderer)
1077 {
1078  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1079  D3DVIEWPORT9 viewport;
1080  D3DMATRIX matrix;
1081 
1082  /* Set the viewport */
1083  viewport.X = renderer->viewport.x;
1084  viewport.Y = renderer->viewport.y;
1085  viewport.Width = renderer->viewport.w;
1086  viewport.Height = renderer->viewport.h;
1087  viewport.MinZ = 0.0f;
1088  viewport.MaxZ = 1.0f;
1089  IDirect3DDevice9_SetViewport(data->device, &viewport);
1090 
1091  /* Set an orthographic projection matrix */
1092  if (renderer->viewport.w && renderer->viewport.h) {
1093  matrix.m[0][0] = 2.0f / renderer->viewport.w;
1094  matrix.m[0][1] = 0.0f;
1095  matrix.m[0][2] = 0.0f;
1096  matrix.m[0][3] = 0.0f;
1097  matrix.m[1][0] = 0.0f;
1098  matrix.m[1][1] = -2.0f / renderer->viewport.h;
1099  matrix.m[1][2] = 0.0f;
1100  matrix.m[1][3] = 0.0f;
1101  matrix.m[2][0] = 0.0f;
1102  matrix.m[2][1] = 0.0f;
1103  matrix.m[2][2] = 1.0f;
1104  matrix.m[2][3] = 0.0f;
1105  matrix.m[3][0] = -1.0f;
1106  matrix.m[3][1] = 1.0f;
1107  matrix.m[3][2] = 0.0f;
1108  matrix.m[3][3] = 1.0f;
1109  IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
1110  }
1111 
1112  return 0;
1113 }
1114 
1115 static int
1116 D3D_UpdateClipRect(SDL_Renderer * renderer)
1117 {
1118  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1119 
1120  if (renderer->clipping_enabled) {
1121  const SDL_Rect *rect = &renderer->clip_rect;
1122  RECT r;
1123  HRESULT result;
1124 
1125  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
1126  r.left = renderer->viewport.x + rect->x;
1127  r.top = renderer->viewport.y + rect->y;
1128  r.right = renderer->viewport.x + rect->x + rect->w;
1129  r.bottom = renderer->viewport.y + rect->y + rect->h;
1130 
1131  result = IDirect3DDevice9_SetScissorRect(data->device, &r);
1132  if (result != D3D_OK) {
1133  D3D_SetError("SetScissor()", result);
1134  return -1;
1135  }
1136  } else {
1137  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
1138  }
1139  return 0;
1140 }
1141 
1142 static int
1143 D3D_RenderClear(SDL_Renderer * renderer)
1144 {
1145  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1146  DWORD color;
1147  HRESULT result;
1148  int BackBufferWidth, BackBufferHeight;
1149 
1150  if (D3D_ActivateRenderer(renderer) < 0) {
1151  return -1;
1152  }
1153 
1154  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1155 
1156  if (renderer->target) {
1157  BackBufferWidth = renderer->target->w;
1158  BackBufferHeight = renderer->target->h;
1159  } else {
1160  BackBufferWidth = data->pparams.BackBufferWidth;
1161  BackBufferHeight = data->pparams.BackBufferHeight;
1162  }
1163 
1164  if (renderer->clipping_enabled) {
1165  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
1166  }
1167 
1168  /* Don't reset the viewport if we don't have to! */
1169  if (!renderer->viewport.x && !renderer->viewport.y &&
1170  renderer->viewport.w == BackBufferWidth &&
1171  renderer->viewport.h == BackBufferHeight) {
1172  result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
1173  } else {
1174  D3DVIEWPORT9 viewport;
1175 
1176  /* Clear is defined to clear the entire render target */
1177  viewport.X = 0;
1178  viewport.Y = 0;
1179  viewport.Width = BackBufferWidth;
1180  viewport.Height = BackBufferHeight;
1181  viewport.MinZ = 0.0f;
1182  viewport.MaxZ = 1.0f;
1183  IDirect3DDevice9_SetViewport(data->device, &viewport);
1184 
1185  result = IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
1186 
1187  /* Reset the viewport */
1188  viewport.X = renderer->viewport.x;
1189  viewport.Y = renderer->viewport.y;
1190  viewport.Width = renderer->viewport.w;
1191  viewport.Height = renderer->viewport.h;
1192  viewport.MinZ = 0.0f;
1193  viewport.MaxZ = 1.0f;
1194  IDirect3DDevice9_SetViewport(data->device, &viewport);
1195  }
1196 
1197  if (renderer->clipping_enabled) {
1198  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
1199  }
1200 
1201  if (FAILED(result)) {
1202  return D3D_SetError("Clear()", result);
1203  }
1204  return 0;
1205 }
1206 
1207 static void
1208 D3D_SetBlendMode(D3D_RenderData * data, SDL_BlendMode blendMode)
1209 {
1210  if (blendMode == SDL_BLENDMODE_NONE) {
1211  IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE);
1212  } else {
1213  IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, TRUE);
1214  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
1215  GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)));
1216  IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
1217  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
1218  if (data->enableSeparateAlphaBlend) {
1219  IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
1220  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)));
1221  IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
1222  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
1223  }
1224  }
1225 }
1226 
1227 static int
1228 D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
1229  int count)
1230 {
1231  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1232  DWORD color;
1233  Vertex *vertices;
1234  int i;
1235  HRESULT result;
1236 
1237  if (D3D_ActivateRenderer(renderer) < 0) {
1238  return -1;
1239  }
1240 
1241  D3D_SetBlendMode(data, renderer->blendMode);
1242 
1243  result =
1244  IDirect3DDevice9_SetTexture(data->device, 0,
1245  (IDirect3DBaseTexture9 *) 0);
1246  if (FAILED(result)) {
1247  return D3D_SetError("SetTexture()", result);
1248  }
1249 
1250  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1251 
1252  vertices = SDL_stack_alloc(Vertex, count);
1253  for (i = 0; i < count; ++i) {
1254  vertices[i].x = points[i].x;
1255  vertices[i].y = points[i].y;
1256  vertices[i].z = 0.0f;
1257  vertices[i].color = color;
1258  vertices[i].u = 0.0f;
1259  vertices[i].v = 0.0f;
1260  }
1261  result =
1262  IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
1263  vertices, sizeof(*vertices));
1264  SDL_stack_free(vertices);
1265  if (FAILED(result)) {
1266  return D3D_SetError("DrawPrimitiveUP()", result);
1267  }
1268  return 0;
1269 }
1270 
1271 static int
1272 D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
1273  int count)
1274 {
1275  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1276  DWORD color;
1277  Vertex *vertices;
1278  int i;
1279  HRESULT result;
1280 
1281  if (D3D_ActivateRenderer(renderer) < 0) {
1282  return -1;
1283  }
1284 
1285  D3D_SetBlendMode(data, renderer->blendMode);
1286 
1287  result =
1288  IDirect3DDevice9_SetTexture(data->device, 0,
1289  (IDirect3DBaseTexture9 *) 0);
1290  if (FAILED(result)) {
1291  return D3D_SetError("SetTexture()", result);
1292  }
1293 
1294  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1295 
1296  vertices = SDL_stack_alloc(Vertex, count);
1297  for (i = 0; i < count; ++i) {
1298  vertices[i].x = points[i].x;
1299  vertices[i].y = points[i].y;
1300  vertices[i].z = 0.0f;
1301  vertices[i].color = color;
1302  vertices[i].u = 0.0f;
1303  vertices[i].v = 0.0f;
1304  }
1305  result =
1306  IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
1307  vertices, sizeof(*vertices));
1308 
1309  /* DirectX 9 has the same line rasterization semantics as GDI,
1310  so we need to close the endpoint of the line */
1311  if (count == 2 ||
1312  points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1313  vertices[0].x = points[count-1].x;
1314  vertices[0].y = points[count-1].y;
1315  result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
1316  }
1317 
1318  SDL_stack_free(vertices);
1319  if (FAILED(result)) {
1320  return D3D_SetError("DrawPrimitiveUP()", result);
1321  }
1322  return 0;
1323 }
1324 
1325 static int
1326 D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
1327  int count)
1328 {
1329  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1330  DWORD color;
1331  int i;
1332  float minx, miny, maxx, maxy;
1333  Vertex vertices[4];
1334  HRESULT result;
1335 
1336  if (D3D_ActivateRenderer(renderer) < 0) {
1337  return -1;
1338  }
1339 
1340  D3D_SetBlendMode(data, renderer->blendMode);
1341 
1342  result =
1343  IDirect3DDevice9_SetTexture(data->device, 0,
1344  (IDirect3DBaseTexture9 *) 0);
1345  if (FAILED(result)) {
1346  return D3D_SetError("SetTexture()", result);
1347  }
1348 
1349  color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1350 
1351  for (i = 0; i < count; ++i) {
1352  const SDL_FRect *rect = &rects[i];
1353 
1354  minx = rect->x;
1355  miny = rect->y;
1356  maxx = rect->x + rect->w;
1357  maxy = rect->y + rect->h;
1358 
1359  vertices[0].x = minx;
1360  vertices[0].y = miny;
1361  vertices[0].z = 0.0f;
1362  vertices[0].color = color;
1363  vertices[0].u = 0.0f;
1364  vertices[0].v = 0.0f;
1365 
1366  vertices[1].x = maxx;
1367  vertices[1].y = miny;
1368  vertices[1].z = 0.0f;
1369  vertices[1].color = color;
1370  vertices[1].u = 0.0f;
1371  vertices[1].v = 0.0f;
1372 
1373  vertices[2].x = maxx;
1374  vertices[2].y = maxy;
1375  vertices[2].z = 0.0f;
1376  vertices[2].color = color;
1377  vertices[2].u = 0.0f;
1378  vertices[2].v = 0.0f;
1379 
1380  vertices[3].x = minx;
1381  vertices[3].y = maxy;
1382  vertices[3].z = 0.0f;
1383  vertices[3].color = color;
1384  vertices[3].u = 0.0f;
1385  vertices[3].v = 0.0f;
1386 
1387  result =
1388  IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
1389  2, vertices, sizeof(*vertices));
1390  if (FAILED(result)) {
1391  return D3D_SetError("DrawPrimitiveUP()", result);
1392  }
1393  }
1394  return 0;
1395 }
1396 
1397 static void
1398 D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
1399 {
1400  if (texturedata->scaleMode != data->scaleMode[index]) {
1401  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER,
1402  texturedata->scaleMode);
1403  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER,
1404  texturedata->scaleMode);
1405  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU,
1406  D3DTADDRESS_CLAMP);
1407  IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV,
1408  D3DTADDRESS_CLAMP);
1409  data->scaleMode[index] = texturedata->scaleMode;
1410  }
1411 }
1412 
1413 static int
1414 D3D_RenderSetupTextureState(SDL_Renderer * renderer, SDL_Texture * texture, LPDIRECT3DPIXELSHADER9 *shader)
1415 {
1416  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1417  D3D_TextureData *texturedata;
1418 
1419  *shader = NULL;
1420 
1421  texturedata = (D3D_TextureData *)texture->driverdata;
1422  if (!texturedata) {
1423  SDL_SetError("Texture is not currently available");
1424  return -1;
1425  }
1426 
1427  D3D_UpdateTextureScaleMode(data, texturedata, 0);
1428 
1429  if (D3D_BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
1430  return -1;
1431  }
1432 
1433  if (texturedata->yuv) {
1434  switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
1436  *shader = data->shaders[SHADER_YUV_JPEG];
1437  break;
1439  *shader = data->shaders[SHADER_YUV_BT601];
1440  break;
1442  *shader = data->shaders[SHADER_YUV_BT709];
1443  break;
1444  default:
1445  return SDL_SetError("Unsupported YUV conversion mode");
1446  }
1447 
1448  D3D_UpdateTextureScaleMode(data, texturedata, 1);
1449  D3D_UpdateTextureScaleMode(data, texturedata, 2);
1450 
1451  if (D3D_BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
1452  return -1;
1453  }
1454  if (D3D_BindTextureRep(data->device, &texturedata->vtexture, 2) < 0) {
1455  return -1;
1456  }
1457  }
1458  return 0;
1459 }
1460 
1461 static int
1462 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1463  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1464 {
1465  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1466  LPDIRECT3DPIXELSHADER9 shader;
1467  float minx, miny, maxx, maxy;
1468  float minu, maxu, minv, maxv;
1469  DWORD color;
1470  Vertex vertices[4];
1471  HRESULT result;
1472 
1473  if (D3D_ActivateRenderer(renderer) < 0) {
1474  return -1;
1475  }
1476 
1477  minx = dstrect->x - 0.5f;
1478  miny = dstrect->y - 0.5f;
1479  maxx = dstrect->x + dstrect->w - 0.5f;
1480  maxy = dstrect->y + dstrect->h - 0.5f;
1481 
1482  minu = (float) srcrect->x / texture->w;
1483  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1484  minv = (float) srcrect->y / texture->h;
1485  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1486 
1487  color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1488 
1489  vertices[0].x = minx;
1490  vertices[0].y = miny;
1491  vertices[0].z = 0.0f;
1492  vertices[0].color = color;
1493  vertices[0].u = minu;
1494  vertices[0].v = minv;
1495 
1496  vertices[1].x = maxx;
1497  vertices[1].y = miny;
1498  vertices[1].z = 0.0f;
1499  vertices[1].color = color;
1500  vertices[1].u = maxu;
1501  vertices[1].v = minv;
1502 
1503  vertices[2].x = maxx;
1504  vertices[2].y = maxy;
1505  vertices[2].z = 0.0f;
1506  vertices[2].color = color;
1507  vertices[2].u = maxu;
1508  vertices[2].v = maxv;
1509 
1510  vertices[3].x = minx;
1511  vertices[3].y = maxy;
1512  vertices[3].z = 0.0f;
1513  vertices[3].color = color;
1514  vertices[3].u = minu;
1515  vertices[3].v = maxv;
1516 
1517  D3D_SetBlendMode(data, texture->blendMode);
1518 
1519  if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) {
1520  return -1;
1521  }
1522 
1523  if (shader) {
1524  result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1525  if (FAILED(result)) {
1526  return D3D_SetError("SetShader()", result);
1527  }
1528  }
1529  result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
1530  vertices, sizeof(*vertices));
1531  if (FAILED(result)) {
1532  D3D_SetError("DrawPrimitiveUP()", result);
1533  }
1534  if (shader) {
1535  IDirect3DDevice9_SetPixelShader(data->device, NULL);
1536  }
1537  return FAILED(result) ? -1 : 0;
1538 }
1539 
1540 
1541 static int
1542 D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1543  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1544  const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
1545 {
1546  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1547  LPDIRECT3DPIXELSHADER9 shader = NULL;
1548  float minx, miny, maxx, maxy;
1549  float minu, maxu, minv, maxv;
1550  float centerx, centery;
1551  DWORD color;
1552  Vertex vertices[4];
1553  Float4X4 modelMatrix;
1554  HRESULT result;
1555 
1556  if (D3D_ActivateRenderer(renderer) < 0) {
1557  return -1;
1558  }
1559 
1560  centerx = center->x;
1561  centery = center->y;
1562 
1563  minx = -centerx;
1564  maxx = dstrect->w - centerx;
1565  miny = -centery;
1566  maxy = dstrect->h - centery;
1567 
1568  minu = (float) srcrect->x / texture->w;
1569  maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1570  minv = (float) srcrect->y / texture->h;
1571  maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1572 
1573  if (flip & SDL_FLIP_HORIZONTAL) {
1574  float tmp = maxu;
1575  maxu = minu;
1576  minu = tmp;
1577  }
1578  if (flip & SDL_FLIP_VERTICAL) {
1579  float tmp = maxv;
1580  maxv = minv;
1581  minv = tmp;
1582  }
1583 
1584  color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1585 
1586  vertices[0].x = minx;
1587  vertices[0].y = miny;
1588  vertices[0].z = 0.0f;
1589  vertices[0].color = color;
1590  vertices[0].u = minu;
1591  vertices[0].v = minv;
1592 
1593  vertices[1].x = maxx;
1594  vertices[1].y = miny;
1595  vertices[1].z = 0.0f;
1596  vertices[1].color = color;
1597  vertices[1].u = maxu;
1598  vertices[1].v = minv;
1599 
1600  vertices[2].x = maxx;
1601  vertices[2].y = maxy;
1602  vertices[2].z = 0.0f;
1603  vertices[2].color = color;
1604  vertices[2].u = maxu;
1605  vertices[2].v = maxv;
1606 
1607  vertices[3].x = minx;
1608  vertices[3].y = maxy;
1609  vertices[3].z = 0.0f;
1610  vertices[3].color = color;
1611  vertices[3].u = minu;
1612  vertices[3].v = maxv;
1613 
1614  D3D_SetBlendMode(data, texture->blendMode);
1615 
1616  if (D3D_RenderSetupTextureState(renderer, texture, &shader) < 0) {
1617  return -1;
1618  }
1619 
1620  /* Rotate and translate */
1621  modelMatrix = MatrixMultiply(
1622  MatrixRotationZ((float)(M_PI * (float) angle / 180.0f)),
1623  MatrixTranslation(dstrect->x + center->x - 0.5f, dstrect->y + center->y - 0.5f, 0));
1624  IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
1625 
1626  if (shader) {
1627  result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1628  if (FAILED(result)) {
1629  D3D_SetError("SetShader()", result);
1630  goto done;
1631  }
1632  }
1633  result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
1634  vertices, sizeof(*vertices));
1635  if (FAILED(result)) {
1636  D3D_SetError("DrawPrimitiveUP()", result);
1637  }
1638 done:
1639  if (shader) {
1640  IDirect3DDevice9_SetPixelShader(data->device, NULL);
1641  }
1642 
1643  modelMatrix = MatrixIdentity();
1644  IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&modelMatrix);
1645 
1646  return FAILED(result) ? -1 : 0;
1647 }
1648 
1649 static int
1650 D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1651  Uint32 format, void * pixels, int pitch)
1652 {
1653  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1654  D3DSURFACE_DESC desc;
1655  LPDIRECT3DSURFACE9 backBuffer;
1656  LPDIRECT3DSURFACE9 surface;
1657  RECT d3drect;
1658  D3DLOCKED_RECT locked;
1659  HRESULT result;
1660 
1661  if (data->currentRenderTarget) {
1662  backBuffer = data->currentRenderTarget;
1663  } else {
1664  backBuffer = data->defaultRenderTarget;
1665  }
1666 
1667  result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
1668  if (FAILED(result)) {
1669  IDirect3DSurface9_Release(backBuffer);
1670  return D3D_SetError("GetDesc()", result);
1671  }
1672 
1673  result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
1674  if (FAILED(result)) {
1675  IDirect3DSurface9_Release(backBuffer);
1676  return D3D_SetError("CreateOffscreenPlainSurface()", result);
1677  }
1678 
1679  result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
1680  if (FAILED(result)) {
1681  IDirect3DSurface9_Release(surface);
1682  IDirect3DSurface9_Release(backBuffer);
1683  return D3D_SetError("GetRenderTargetData()", result);
1684  }
1685 
1686  d3drect.left = rect->x;
1687  d3drect.right = rect->x + rect->w;
1688  d3drect.top = rect->y;
1689  d3drect.bottom = rect->y + rect->h;
1690 
1691  result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
1692  if (FAILED(result)) {
1693  IDirect3DSurface9_Release(surface);
1694  IDirect3DSurface9_Release(backBuffer);
1695  return D3D_SetError("LockRect()", result);
1696  }
1697 
1698  SDL_ConvertPixels(rect->w, rect->h,
1699  D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
1700  format, pixels, pitch);
1701 
1702  IDirect3DSurface9_UnlockRect(surface);
1703 
1704  IDirect3DSurface9_Release(surface);
1705 
1706  return 0;
1707 }
1708 
1709 static void
1710 D3D_RenderPresent(SDL_Renderer * renderer)
1711 {
1712  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1713  HRESULT result;
1714 
1715  if (!data->beginScene) {
1716  IDirect3DDevice9_EndScene(data->device);
1717  data->beginScene = SDL_TRUE;
1718  }
1719 
1720  result = IDirect3DDevice9_TestCooperativeLevel(data->device);
1721  if (result == D3DERR_DEVICELOST) {
1722  /* We'll reset later */
1723  return;
1724  }
1725  if (result == D3DERR_DEVICENOTRESET) {
1726  D3D_Reset(renderer);
1727  }
1728  result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
1729  if (FAILED(result)) {
1730  D3D_SetError("Present()", result);
1731  }
1732 }
1733 
1734 static void
1735 D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1736 {
1737  D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1738 
1739  if (!data) {
1740  return;
1741  }
1742  D3D_DestroyTextureRep(&data->texture);
1743  D3D_DestroyTextureRep(&data->utexture);
1744  D3D_DestroyTextureRep(&data->vtexture);
1745  SDL_free(data->pixels);
1746  SDL_free(data);
1747  texture->driverdata = NULL;
1748 }
1749 
1750 static void
1751 D3D_DestroyRenderer(SDL_Renderer * renderer)
1752 {
1753  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1754 
1755  if (data) {
1756  int i;
1757 
1758  /* Release the render target */
1759  if (data->defaultRenderTarget) {
1760  IDirect3DSurface9_Release(data->defaultRenderTarget);
1761  data->defaultRenderTarget = NULL;
1762  }
1763  if (data->currentRenderTarget != NULL) {
1764  IDirect3DSurface9_Release(data->currentRenderTarget);
1765  data->currentRenderTarget = NULL;
1766  }
1767  for (i = 0; i < SDL_arraysize(data->shaders); ++i) {
1768  if (data->shaders[i]) {
1769  IDirect3DPixelShader9_Release(data->shaders[i]);
1770  data->shaders[i] = NULL;
1771  }
1772  }
1773  if (data->device) {
1774  IDirect3DDevice9_Release(data->device);
1775  data->device = NULL;
1776  }
1777  if (data->d3d) {
1778  IDirect3D9_Release(data->d3d);
1779  SDL_UnloadObject(data->d3dDLL);
1780  }
1781  SDL_free(data);
1782  }
1783  SDL_free(renderer);
1784 }
1785 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
1786 
1787 #ifdef __WIN32__
1788 /* This function needs to always exist on Windows, for the Dynamic API. */
1791 {
1792  IDirect3DDevice9 *device = NULL;
1793 
1794 #if SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED
1795  D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1796 
1797  /* Make sure that this is a D3D renderer */
1798  if (renderer->DestroyRenderer != D3D_DestroyRenderer) {
1799  SDL_SetError("Renderer is not a D3D renderer");
1800  return NULL;
1801  }
1802 
1803  device = data->device;
1804  if (device) {
1805  IDirect3DDevice9_AddRef(device);
1806  }
1807 #endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
1808 
1809  return device;
1810 }
1811 #endif /* __WIN32__ */
1812 
1813 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2252
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:65
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)
#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:91
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
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:2280
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
#define SDL_GetWindowFlags
SDL_version version
Definition: SDL_syswm.h:196
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2266
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
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:99
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)
#define SDL_GetWindowSize
#define FAILED(x)
Definition: SDL_directx.h:54
SDL_Texture * next
Definition: SDL_sysrender.h:81
#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:2287
SDL_Texture * target
static SDL_Renderer * renderer
uint8_t Uint8
Definition: SDL_stdinc.h:179
#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:195
#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:161
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2273
#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
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_Rect viewport
Definition: testviewport.c:28
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2259
GLuint color
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:89
GLfloat angle
Uint32 num_texture_formats
Definition: SDL_render.h:82
Uint32 format
Definition: SDL_sysrender.h:60
union SDL_SysWMinfo::@18 info
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
void * driverdata
Definition: SDL_sysrender.h:78
General event structure.
Definition: SDL_events.h:557
#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:92
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
SDL_ScaleMode scaleMode
Definition: SDL_sysrender.h:66
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