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