comparison src/video/windows/SDL_d3drender.c @ 5062:e8916fe9cfc8

Fixed bug #925 Changed "win32" to "windows"
author Sam Lantinga <slouken@libsdl.org>
date Thu, 20 Jan 2011 18:04:05 -0800
parents src/video/win32/SDL_d3drender.c@aa8888658021
children da10636e5eca
comparison
equal deleted inserted replaced
5061:9e9940eae455 5062:e8916fe9cfc8
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #if SDL_VIDEO_RENDER_D3D
25
26 #include "SDL_windowsvideo.h"
27 #include "../SDL_yuv_sw_c.h"
28
29 #ifdef ASSEMBLE_SHADER
30 ///////////////////////////////////////////////////////////////////////////
31 // ID3DXBuffer:
32 // ------------
33 // The buffer object is used by D3DX to return arbitrary size data.
34 //
35 // GetBufferPointer -
36 // Returns a pointer to the beginning of the buffer.
37 //
38 // GetBufferSize -
39 // Returns the size of the buffer, in bytes.
40 ///////////////////////////////////////////////////////////////////////////
41
42 typedef interface ID3DXBuffer ID3DXBuffer;
43 typedef interface ID3DXBuffer *LPD3DXBUFFER;
44
45 // {8BA5FB08-5195-40e2-AC58-0D989C3A0102}
46 DEFINE_GUID(IID_ID3DXBuffer,
47 0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
48
49 #undef INTERFACE
50 #define INTERFACE ID3DXBuffer
51
52 typedef interface ID3DXBuffer {
53 const struct ID3DXBufferVtbl FAR* lpVtbl;
54 } ID3DXBuffer;
55 typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
56 const struct ID3DXBufferVtbl
57 {
58 // IUnknown
59 STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
60 STDMETHOD_(ULONG, AddRef)(THIS) PURE;
61 STDMETHOD_(ULONG, Release)(THIS) PURE;
62
63 // ID3DXBuffer
64 STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
65 STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
66 };
67
68 HRESULT WINAPI
69 D3DXAssembleShader(
70 LPCSTR pSrcData,
71 UINT SrcDataLen,
72 CONST LPVOID* pDefines,
73 LPVOID pInclude,
74 DWORD Flags,
75 LPD3DXBUFFER* ppShader,
76 LPD3DXBUFFER* ppErrorMsgs);
77
78 #endif /* ASSEMBLE_SHADER */
79
80
81 /* Direct3D renderer implementation */
82
83 #if 1 /* This takes more memory but you won't lose your texture data */
84 #define D3DPOOL_SDL D3DPOOL_MANAGED
85 #define SDL_MEMORY_POOL_MANAGED
86 #else
87 #define D3DPOOL_SDL D3DPOOL_DEFAULT
88 #define SDL_MEMORY_POOL_DEFAULT
89 #endif
90
91 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
92 static int D3D_DisplayModeChanged(SDL_Renderer * renderer);
93 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
94 static int D3D_QueryTexturePixels(SDL_Renderer * renderer,
95 SDL_Texture * texture, void **pixels,
96 int *pitch);
97 static int D3D_SetTexturePalette(SDL_Renderer * renderer,
98 SDL_Texture * texture,
99 const SDL_Color * colors, int firstcolor,
100 int ncolors);
101 static int D3D_GetTexturePalette(SDL_Renderer * renderer,
102 SDL_Texture * texture, SDL_Color * colors,
103 int firstcolor, int ncolors);
104 static int D3D_SetTextureColorMod(SDL_Renderer * renderer,
105 SDL_Texture * texture);
106 static int D3D_SetTextureAlphaMod(SDL_Renderer * renderer,
107 SDL_Texture * texture);
108 static int D3D_SetTextureBlendMode(SDL_Renderer * renderer,
109 SDL_Texture * texture);
110 static int D3D_SetTextureScaleMode(SDL_Renderer * renderer,
111 SDL_Texture * texture);
112 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
113 const SDL_Rect * rect, const void *pixels,
114 int pitch);
115 static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
116 const SDL_Rect * rect, int markDirty,
117 void **pixels, int *pitch);
118 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
119 static void D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
120 int numrects, const SDL_Rect * rects);
121 static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
122 const SDL_Point * points, int count);
123 static int D3D_RenderDrawLines(SDL_Renderer * renderer,
124 const SDL_Point * points, int count);
125 static int D3D_RenderDrawRects(SDL_Renderer * renderer,
126 const SDL_Rect ** rects, int count);
127 static int D3D_RenderFillRects(SDL_Renderer * renderer,
128 const SDL_Rect ** rects, int count);
129 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
130 const SDL_Rect * srcrect, const SDL_Rect * dstrect);
131 static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
132 Uint32 format, void * pixels, int pitch);
133 static int D3D_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
134 Uint32 format, const void * pixels, int pitch);
135 static void D3D_RenderPresent(SDL_Renderer * renderer);
136 static void D3D_DestroyTexture(SDL_Renderer * renderer,
137 SDL_Texture * texture);
138 static void D3D_DestroyRenderer(SDL_Renderer * renderer);
139
140
141 SDL_RenderDriver D3D_RenderDriver = {
142 D3D_CreateRenderer,
143 {
144 "d3d",
145 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
146 SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
147 SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_PRESENTVSYNC |
148 SDL_RENDERER_ACCELERATED),
149 (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
150 SDL_TEXTUREMODULATE_ALPHA),
151 (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
152 SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
153 (SDL_SCALEMODE_NONE | SDL_SCALEMODE_FAST |
154 SDL_SCALEMODE_SLOW | SDL_SCALEMODE_BEST),
155 0,
156 {0},
157 0,
158 0}
159 };
160
161 typedef struct
162 {
163 IDirect3D9 *d3d;
164 IDirect3DDevice9 *device;
165 UINT adapter;
166 D3DPRESENT_PARAMETERS pparams;
167 LPDIRECT3DPIXELSHADER9 ps_mask;
168 SDL_bool beginScene;
169 } D3D_RenderData;
170
171 typedef struct
172 {
173 SDL_SW_YUVTexture *yuv;
174 Uint32 format;
175 IDirect3DTexture9 *texture;
176 } D3D_TextureData;
177
178 typedef struct
179 {
180 float x, y, z;
181 float rhw;
182 DWORD color;
183 float u, v;
184 } Vertex;
185
186 static void
187 D3D_SetError(const char *prefix, HRESULT result)
188 {
189 const char *error;
190
191 switch (result) {
192 case D3DERR_WRONGTEXTUREFORMAT:
193 error = "WRONGTEXTUREFORMAT";
194 break;
195 case D3DERR_UNSUPPORTEDCOLOROPERATION:
196 error = "UNSUPPORTEDCOLOROPERATION";
197 break;
198 case D3DERR_UNSUPPORTEDCOLORARG:
199 error = "UNSUPPORTEDCOLORARG";
200 break;
201 case D3DERR_UNSUPPORTEDALPHAOPERATION:
202 error = "UNSUPPORTEDALPHAOPERATION";
203 break;
204 case D3DERR_UNSUPPORTEDALPHAARG:
205 error = "UNSUPPORTEDALPHAARG";
206 break;
207 case D3DERR_TOOMANYOPERATIONS:
208 error = "TOOMANYOPERATIONS";
209 break;
210 case D3DERR_CONFLICTINGTEXTUREFILTER:
211 error = "CONFLICTINGTEXTUREFILTER";
212 break;
213 case D3DERR_UNSUPPORTEDFACTORVALUE:
214 error = "UNSUPPORTEDFACTORVALUE";
215 break;
216 case D3DERR_CONFLICTINGRENDERSTATE:
217 error = "CONFLICTINGRENDERSTATE";
218 break;
219 case D3DERR_UNSUPPORTEDTEXTUREFILTER:
220 error = "UNSUPPORTEDTEXTUREFILTER";
221 break;
222 case D3DERR_CONFLICTINGTEXTUREPALETTE:
223 error = "CONFLICTINGTEXTUREPALETTE";
224 break;
225 case D3DERR_DRIVERINTERNALERROR:
226 error = "DRIVERINTERNALERROR";
227 break;
228 case D3DERR_NOTFOUND:
229 error = "NOTFOUND";
230 break;
231 case D3DERR_MOREDATA:
232 error = "MOREDATA";
233 break;
234 case D3DERR_DEVICELOST:
235 error = "DEVICELOST";
236 break;
237 case D3DERR_DEVICENOTRESET:
238 error = "DEVICENOTRESET";
239 break;
240 case D3DERR_NOTAVAILABLE:
241 error = "NOTAVAILABLE";
242 break;
243 case D3DERR_OUTOFVIDEOMEMORY:
244 error = "OUTOFVIDEOMEMORY";
245 break;
246 case D3DERR_INVALIDDEVICE:
247 error = "INVALIDDEVICE";
248 break;
249 case D3DERR_INVALIDCALL:
250 error = "INVALIDCALL";
251 break;
252 case D3DERR_DRIVERINVALIDCALL:
253 error = "DRIVERINVALIDCALL";
254 break;
255 case D3DERR_WASSTILLDRAWING:
256 error = "WASSTILLDRAWING";
257 break;
258 default:
259 error = "UNKNOWN";
260 break;
261 }
262 SDL_SetError("%s: %s", prefix, error);
263 }
264
265 static D3DFORMAT
266 PixelFormatToD3DFMT(Uint32 format)
267 {
268 switch (format) {
269 case SDL_PIXELFORMAT_INDEX8:
270 return D3DFMT_P8;
271 case SDL_PIXELFORMAT_RGB332:
272 return D3DFMT_R3G3B2;
273 case SDL_PIXELFORMAT_RGB444:
274 return D3DFMT_X4R4G4B4;
275 case SDL_PIXELFORMAT_RGB555:
276 return D3DFMT_X1R5G5B5;
277 case SDL_PIXELFORMAT_ARGB4444:
278 return D3DFMT_A4R4G4B4;
279 case SDL_PIXELFORMAT_ARGB1555:
280 return D3DFMT_A1R5G5B5;
281 case SDL_PIXELFORMAT_RGB565:
282 return D3DFMT_R5G6B5;
283 case SDL_PIXELFORMAT_RGB888:
284 return D3DFMT_X8R8G8B8;
285 case SDL_PIXELFORMAT_ARGB8888:
286 return D3DFMT_A8R8G8B8;
287 case SDL_PIXELFORMAT_ARGB2101010:
288 return D3DFMT_A2R10G10B10;
289 case SDL_PIXELFORMAT_YV12:
290 return MAKEFOURCC('Y','V','1','2');
291 case SDL_PIXELFORMAT_IYUV:
292 return MAKEFOURCC('I','4','2','0');
293 case SDL_PIXELFORMAT_UYVY:
294 return D3DFMT_UYVY;
295 case SDL_PIXELFORMAT_YUY2:
296 return D3DFMT_YUY2;
297 default:
298 return D3DFMT_UNKNOWN;
299 }
300 }
301
302 static UINT D3D_FindAdapter(IDirect3D9 * d3d, SDL_VideoDisplay * display)
303 {
304 SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
305 UINT adapter, count;
306
307 count = IDirect3D9_GetAdapterCount(d3d);
308 for (adapter = 0; adapter < count; ++adapter) {
309 HRESULT result;
310 D3DADAPTER_IDENTIFIER9 info;
311 char *name;
312
313 result = IDirect3D9_GetAdapterIdentifier(d3d, adapter, 0, &info);
314 if (FAILED(result)) {
315 continue;
316 }
317 name = WIN_StringToUTF8(displaydata->DeviceName);
318 if (SDL_strcmp(name, info.DeviceName) == 0) {
319 SDL_free(name);
320 return adapter;
321 }
322 SDL_free(name);
323 }
324
325 /* This should never happen, but just in case... */
326 return D3DADAPTER_DEFAULT;
327 }
328
329 static SDL_bool
330 D3D_IsTextureFormatAvailable(IDirect3D9 * d3d, UINT adapter,
331 Uint32 display_format,
332 Uint32 texture_format)
333 {
334 HRESULT result;
335
336 result = IDirect3D9_CheckDeviceFormat(d3d, adapter,
337 D3DDEVTYPE_HAL,
338 PixelFormatToD3DFMT(display_format),
339 0,
340 D3DRTYPE_TEXTURE,
341 PixelFormatToD3DFMT
342 (texture_format));
343 return FAILED(result) ? SDL_FALSE : SDL_TRUE;
344 }
345
346 static void
347 UpdateYUVTextureData(SDL_Texture * texture)
348 {
349 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
350 SDL_Rect rect;
351 RECT d3drect;
352 D3DLOCKED_RECT locked;
353 HRESULT result;
354
355 d3drect.left = 0;
356 d3drect.right = texture->w;
357 d3drect.top = 0;
358 d3drect.bottom = texture->h;
359
360 result =
361 IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
362 if (FAILED(result)) {
363 return;
364 }
365
366 rect.x = 0;
367 rect.y = 0;
368 rect.w = texture->w;
369 rect.h = texture->h;
370 SDL_SW_CopyYUVToRGB(data->yuv, &rect, data->format, texture->w,
371 texture->h, locked.pBits, locked.Pitch);
372
373 IDirect3DTexture9_UnlockRect(data->texture, 0);
374 }
375
376 void
377 D3D_AddRenderDriver(_THIS)
378 {
379 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
380 SDL_RendererInfo *info = &D3D_RenderDriver.info;
381
382 if (data->d3d) {
383 int i, j;
384 int formats[] = {
385 SDL_PIXELFORMAT_INDEX8,
386 SDL_PIXELFORMAT_RGB332,
387 SDL_PIXELFORMAT_RGB444,
388 SDL_PIXELFORMAT_RGB555,
389 SDL_PIXELFORMAT_ARGB4444,
390 SDL_PIXELFORMAT_ARGB1555,
391 SDL_PIXELFORMAT_RGB565,
392 SDL_PIXELFORMAT_RGB888,
393 SDL_PIXELFORMAT_ARGB8888,
394 SDL_PIXELFORMAT_ARGB2101010,
395 };
396
397 for (i = 0; i < _this->num_displays; ++i) {
398 SDL_VideoDisplay *display = &_this->displays[i];
399 SDL_DisplayMode *mode = &display->desktop_mode;
400 UINT adapter = D3D_FindAdapter(data->d3d, display);
401
402 /* Get the matching D3D adapter for this display */
403 info->num_texture_formats = 0;
404 for (j = 0; j < SDL_arraysize(formats); ++j) {
405 if (D3D_IsTextureFormatAvailable
406 (data->d3d, adapter, mode->format, formats[j])) {
407 info->texture_formats[info->num_texture_formats++] =
408 formats[j];
409 }
410 }
411 info->texture_formats[info->num_texture_formats++] =
412 SDL_PIXELFORMAT_YV12;
413 info->texture_formats[info->num_texture_formats++] =
414 SDL_PIXELFORMAT_IYUV;
415 info->texture_formats[info->num_texture_formats++] =
416 SDL_PIXELFORMAT_YUY2;
417 info->texture_formats[info->num_texture_formats++] =
418 SDL_PIXELFORMAT_UYVY;
419 info->texture_formats[info->num_texture_formats++] =
420 SDL_PIXELFORMAT_YVYU;
421
422 SDL_AddRenderDriver(display, &D3D_RenderDriver);
423 }
424 }
425 }
426
427 SDL_Renderer *
428 D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
429 {
430 SDL_VideoDisplay *display = window->display;
431 SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata;
432 SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
433 SDL_Renderer *renderer;
434 D3D_RenderData *data;
435 HRESULT result;
436 D3DPRESENT_PARAMETERS pparams;
437 IDirect3DSwapChain9 *chain;
438 D3DCAPS9 caps;
439
440 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
441 if (!renderer) {
442 SDL_OutOfMemory();
443 return NULL;
444 }
445
446 data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
447 if (!data) {
448 D3D_DestroyRenderer(renderer);
449 SDL_OutOfMemory();
450 return NULL;
451 }
452 data->d3d = videodata->d3d;
453
454 videodata->render = RENDER_D3D;
455
456 renderer->DisplayModeChanged = D3D_DisplayModeChanged;
457 renderer->CreateTexture = D3D_CreateTexture;
458 renderer->QueryTexturePixels = D3D_QueryTexturePixels;
459 renderer->SetTexturePalette = D3D_SetTexturePalette;
460 renderer->GetTexturePalette = D3D_GetTexturePalette;
461 renderer->SetTextureColorMod = D3D_SetTextureColorMod;
462 renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod;
463 renderer->SetTextureBlendMode = D3D_SetTextureBlendMode;
464 renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
465 renderer->UpdateTexture = D3D_UpdateTexture;
466 renderer->LockTexture = D3D_LockTexture;
467 renderer->UnlockTexture = D3D_UnlockTexture;
468 renderer->DirtyTexture = D3D_DirtyTexture;
469 renderer->RenderDrawPoints = D3D_RenderDrawPoints;
470 renderer->RenderDrawLines = D3D_RenderDrawLines;
471 renderer->RenderDrawRects = D3D_RenderDrawRects;
472 renderer->RenderFillRects = D3D_RenderFillRects;
473 renderer->RenderCopy = D3D_RenderCopy;
474 renderer->RenderReadPixels = D3D_RenderReadPixels;
475 renderer->RenderWritePixels = D3D_RenderWritePixels;
476 renderer->RenderPresent = D3D_RenderPresent;
477 renderer->DestroyTexture = D3D_DestroyTexture;
478 renderer->DestroyRenderer = D3D_DestroyRenderer;
479 renderer->info = D3D_RenderDriver.info;
480 renderer->window = window;
481 renderer->driverdata = data;
482
483 renderer->info.flags = SDL_RENDERER_ACCELERATED;
484
485 SDL_zero(pparams);
486 pparams.BackBufferWidth = window->w;
487 pparams.BackBufferHeight = window->h;
488 if (window->flags & SDL_WINDOW_FULLSCREEN) {
489 pparams.BackBufferFormat =
490 PixelFormatToD3DFMT(window->fullscreen_mode.format);
491 } else {
492 pparams.BackBufferFormat = D3DFMT_UNKNOWN;
493 }
494 if (flags & SDL_RENDERER_PRESENTFLIP2) {
495 pparams.BackBufferCount = 2;
496 pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
497 } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
498 pparams.BackBufferCount = 3;
499 pparams.SwapEffect = D3DSWAPEFFECT_FLIP;
500 } else if (flags & SDL_RENDERER_PRESENTCOPY) {
501 pparams.BackBufferCount = 1;
502 pparams.SwapEffect = D3DSWAPEFFECT_COPY;
503 } else {
504 pparams.BackBufferCount = 1;
505 pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
506 }
507 if (window->flags & SDL_WINDOW_FULLSCREEN) {
508 pparams.Windowed = FALSE;
509 pparams.FullScreen_RefreshRateInHz =
510 window->fullscreen_mode.refresh_rate;
511 } else {
512 pparams.Windowed = TRUE;
513 pparams.FullScreen_RefreshRateInHz = 0;
514 }
515 if (flags & SDL_RENDERER_PRESENTVSYNC) {
516 pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
517 } else {
518 pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
519 }
520
521 data->adapter = D3D_FindAdapter(videodata->d3d, display);
522 IDirect3D9_GetDeviceCaps(videodata->d3d, data->adapter,
523 D3DDEVTYPE_HAL, &caps);
524
525 result = IDirect3D9_CreateDevice(videodata->d3d, data->adapter,
526 D3DDEVTYPE_HAL,
527 windowdata->hwnd,
528 (caps.
529 DevCaps &
530 D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
531 D3DCREATE_HARDWARE_VERTEXPROCESSING :
532 D3DCREATE_SOFTWARE_VERTEXPROCESSING,
533 &pparams, &data->device);
534 if (FAILED(result)) {
535 D3D_DestroyRenderer(renderer);
536 D3D_SetError("CreateDevice()", result);
537 return NULL;
538 }
539 data->beginScene = SDL_TRUE;
540
541 /* Get presentation parameters to fill info */
542 result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
543 if (FAILED(result)) {
544 D3D_DestroyRenderer(renderer);
545 D3D_SetError("GetSwapChain()", result);
546 return NULL;
547 }
548 result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
549 if (FAILED(result)) {
550 IDirect3DSwapChain9_Release(chain);
551 D3D_DestroyRenderer(renderer);
552 D3D_SetError("GetPresentParameters()", result);
553 return NULL;
554 }
555 IDirect3DSwapChain9_Release(chain);
556 switch (pparams.SwapEffect) {
557 case D3DSWAPEFFECT_COPY:
558 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
559 break;
560 case D3DSWAPEFFECT_FLIP:
561 switch (pparams.BackBufferCount) {
562 case 2:
563 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
564 break;
565 case 3:
566 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
567 break;
568 }
569 break;
570 case D3DSWAPEFFECT_DISCARD:
571 renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD;
572 break;
573 }
574 if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
575 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
576 }
577 data->pparams = pparams;
578
579 IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
580 renderer->info.max_texture_width = caps.MaxTextureWidth;
581 renderer->info.max_texture_height = caps.MaxTextureHeight;
582
583 /* Set up parameters for rendering */
584 IDirect3DDevice9_SetVertexShader(data->device, NULL);
585 IDirect3DDevice9_SetFVF(data->device,
586 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
587 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
588 IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
589 D3DCULL_NONE);
590 IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
591 /* Enable color modulation by diffuse color */
592 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
593 D3DTOP_MODULATE);
594 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
595 D3DTA_TEXTURE);
596 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
597 D3DTA_DIFFUSE);
598 /* Enable alpha modulation by diffuse alpha */
599 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
600 D3DTOP_MODULATE);
601 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
602 D3DTA_TEXTURE);
603 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
604 D3DTA_DIFFUSE);
605 /* Disable second texture stage, since we're done */
606 IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
607 D3DTOP_DISABLE);
608 IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
609 D3DTOP_DISABLE);
610
611 {
612 #ifdef ASSEMBLE_SHADER
613 const char *shader_text =
614 "ps_1_1\n"
615 "def c0, 0, 0, 0, 0.496\n"
616 "def c1, 0, 0, 0, 1\n"
617 "def c2, 0, 0, 0, -1\n"
618 "tex t0\n"
619 "mul r1, t0, v0\n"
620 "add r0, r1, c0\n"
621 "cnd r0, r0.a, c1, c2\n"
622 "add r0, r0, r1\n";
623 LPD3DXBUFFER pCode; // buffer with the assembled shader code
624 LPD3DXBUFFER pErrorMsgs; // buffer with error messages
625 LPDWORD shader_data;
626 DWORD shader_size;
627 result = D3DXAssembleShader( shader_text, SDL_strlen(shader_text), NULL, NULL, 0, &pCode, &pErrorMsgs );
628 if (FAILED(result)) {
629 D3D_SetError("D3DXAssembleShader()", result);
630 }
631 shader_data = (DWORD*)pCode->lpVtbl->GetBufferPointer(pCode);
632 shader_size = pCode->lpVtbl->GetBufferSize(pCode);
633 #else
634 const DWORD shader_data[] = {
635 0xffff0101,0x00000051,0xa00f0000,0x00000000,0x00000000,0x00000000,
636 0x3efdf3b6,0x00000051,0xa00f0001,0x00000000,0x00000000,0x00000000,
637 0x3f800000,0x00000051,0xa00f0002,0x00000000,0x00000000,0x00000000,
638 0xbf800000,0x00000042,0xb00f0000,0x00000005,0x800f0001,0xb0e40000,
639 0x90e40000,0x00000002,0x800f0000,0x80e40001,0xa0e40000,0x00000050,
640 0x800f0000,0x80ff0000,0xa0e40001,0xa0e40002,0x00000002,0x800f0000,
641 0x80e40000,0x80e40001,0x0000ffff
642 };
643 #endif
644 result = IDirect3DDevice9_CreatePixelShader(data->device, shader_data, &data->ps_mask);
645 if (FAILED(result)) {
646 D3D_SetError("CreatePixelShader()", result);
647 }
648 }
649
650 return renderer;
651 }
652
653 static int
654 D3D_Reset(SDL_Renderer * renderer)
655 {
656 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
657 HRESULT result;
658
659 result = IDirect3DDevice9_Reset(data->device, &data->pparams);
660 if (FAILED(result)) {
661 if (result == D3DERR_DEVICELOST) {
662 /* Don't worry about it, we'll reset later... */
663 return 0;
664 } else {
665 D3D_SetError("Reset()", result);
666 return -1;
667 }
668 }
669 IDirect3DDevice9_SetVertexShader(data->device, NULL);
670 IDirect3DDevice9_SetFVF(data->device,
671 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
672 IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
673 D3DCULL_NONE);
674 IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
675 return 0;
676 }
677
678 static int
679 D3D_DisplayModeChanged(SDL_Renderer * renderer)
680 {
681 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
682 SDL_Window *window = renderer->window;
683 SDL_VideoDisplay *display = window->display;
684
685 data->pparams.BackBufferWidth = window->w;
686 data->pparams.BackBufferHeight = window->h;
687 if (window->flags & SDL_WINDOW_FULLSCREEN) {
688 data->pparams.BackBufferFormat =
689 PixelFormatToD3DFMT(window->fullscreen_mode.format);
690 } else {
691 data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
692 }
693 return D3D_Reset(renderer);
694 }
695
696 static int
697 D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
698 {
699 D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
700 SDL_Window *window = renderer->window;
701 SDL_VideoDisplay *display = window->display;
702 Uint32 display_format = display->current_mode.format;
703 D3D_TextureData *data;
704 HRESULT result;
705
706 data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
707 if (!data) {
708 SDL_OutOfMemory();
709 return -1;
710 }
711
712 texture->driverdata = data;
713
714 if (SDL_ISPIXELFORMAT_FOURCC(texture->format) &&
715 (texture->format != SDL_PIXELFORMAT_YUY2 ||
716 !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
717 display_format, texture->format))
718 && (texture->format != SDL_PIXELFORMAT_YVYU
719 || !D3D_IsTextureFormatAvailable(renderdata->d3d, renderdata->adapter,
720 display_format, texture->format))) {
721 data->yuv =
722 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
723 if (!data->yuv) {
724 return -1;
725 }
726 data->format = display->current_mode.format;
727 } else {
728 data->format = texture->format;
729 }
730
731 result =
732 IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
733 texture->h, 1, 0,
734 PixelFormatToD3DFMT(data->format),
735 D3DPOOL_SDL, &data->texture, NULL);
736 if (FAILED(result)) {
737 D3D_SetError("CreateTexture()", result);
738 return -1;
739 }
740
741 return 0;
742 }
743
744 static int
745 D3D_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
746 void **pixels, int *pitch)
747 {
748 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
749
750 if (data->yuv) {
751 return SDL_SW_QueryYUVTexturePixels(data->yuv, pixels, pitch);
752 } else {
753 /* D3D textures don't have their pixels hanging out */
754 return -1;
755 }
756 }
757
758 static int
759 D3D_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
760 const SDL_Color * colors, int firstcolor, int ncolors)
761 {
762 D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
763 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
764
765 return 0;
766 }
767
768 static int
769 D3D_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
770 SDL_Color * colors, int firstcolor, int ncolors)
771 {
772 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
773
774 return 0;
775 }
776
777 static int
778 D3D_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
779 {
780 return 0;
781 }
782
783 static int
784 D3D_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
785 {
786 return 0;
787 }
788
789 static int
790 D3D_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
791 {
792 switch (texture->blendMode) {
793 case SDL_BLENDMODE_NONE:
794 case SDL_BLENDMODE_MASK:
795 case SDL_BLENDMODE_BLEND:
796 case SDL_BLENDMODE_ADD:
797 case SDL_BLENDMODE_MOD:
798 return 0;
799 default:
800 SDL_Unsupported();
801 texture->blendMode = SDL_BLENDMODE_NONE;
802 return -1;
803 }
804 }
805
806 static int
807 D3D_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
808 {
809 switch (texture->scaleMode) {
810 case SDL_SCALEMODE_NONE:
811 case SDL_SCALEMODE_FAST:
812 case SDL_SCALEMODE_SLOW:
813 case SDL_SCALEMODE_BEST:
814 return 0;
815 default:
816 SDL_Unsupported();
817 texture->scaleMode = SDL_SCALEMODE_NONE;
818 return -1;
819 }
820 return 0;
821 }
822
823 static int
824 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
825 const SDL_Rect * rect, const void *pixels, int pitch)
826 {
827 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
828 D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
829
830 if (data->yuv) {
831 if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) {
832 return -1;
833 }
834 UpdateYUVTextureData(texture);
835 return 0;
836 } else {
837 #ifdef SDL_MEMORY_POOL_DEFAULT
838 IDirect3DTexture9 *temp;
839 RECT d3drect;
840 D3DLOCKED_RECT locked;
841 const Uint8 *src;
842 Uint8 *dst;
843 int row, length;
844 HRESULT result;
845
846 result =
847 IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
848 texture->h, 1, 0,
849 PixelFormatToD3DFMT(texture->
850 format),
851 D3DPOOL_SYSTEMMEM, &temp, NULL);
852 if (FAILED(result)) {
853 D3D_SetError("CreateTexture()", result);
854 return -1;
855 }
856
857 d3drect.left = rect->x;
858 d3drect.right = rect->x + rect->w;
859 d3drect.top = rect->y;
860 d3drect.bottom = rect->y + rect->h;
861
862 result = IDirect3DTexture9_LockRect(temp, 0, &locked, &d3drect, 0);
863 if (FAILED(result)) {
864 IDirect3DTexture9_Release(temp);
865 D3D_SetError("LockRect()", result);
866 return -1;
867 }
868
869 src = pixels;
870 dst = locked.pBits;
871 length = rect->w * SDL_BYTESPERPIXEL(texture->format);
872 for (row = 0; row < rect->h; ++row) {
873 SDL_memcpy(dst, src, length);
874 src += pitch;
875 dst += locked.Pitch;
876 }
877 IDirect3DTexture9_UnlockRect(temp, 0);
878
879 result =
880 IDirect3DDevice9_UpdateTexture(renderdata->device,
881 (IDirect3DBaseTexture9 *) temp,
882 (IDirect3DBaseTexture9 *)
883 data->texture);
884 IDirect3DTexture9_Release(temp);
885 if (FAILED(result)) {
886 D3D_SetError("UpdateTexture()", result);
887 return -1;
888 }
889 #else
890 RECT d3drect;
891 D3DLOCKED_RECT locked;
892 const Uint8 *src;
893 Uint8 *dst;
894 int row, length;
895 HRESULT result;
896
897 d3drect.left = rect->x;
898 d3drect.right = rect->x + rect->w;
899 d3drect.top = rect->y;
900 d3drect.bottom = rect->y + rect->h;
901
902 result =
903 IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
904 0);
905 if (FAILED(result)) {
906 D3D_SetError("LockRect()", result);
907 return -1;
908 }
909
910 src = pixels;
911 dst = locked.pBits;
912 length = rect->w * SDL_BYTESPERPIXEL(texture->format);
913 for (row = 0; row < rect->h; ++row) {
914 SDL_memcpy(dst, src, length);
915 src += pitch;
916 dst += locked.Pitch;
917 }
918 IDirect3DTexture9_UnlockRect(data->texture, 0);
919 #endif // SDL_MEMORY_POOL_DEFAULT
920
921 return 0;
922 }
923 }
924
925 static int
926 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
927 const SDL_Rect * rect, int markDirty, void **pixels,
928 int *pitch)
929 {
930 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
931
932 if (data->yuv) {
933 return SDL_SW_LockYUVTexture(data->yuv, rect, markDirty, pixels,
934 pitch);
935 } else {
936 RECT d3drect;
937 D3DLOCKED_RECT locked;
938 HRESULT result;
939
940 d3drect.left = rect->x;
941 d3drect.right = rect->x + rect->w;
942 d3drect.top = rect->y;
943 d3drect.bottom = rect->y + rect->h;
944
945 result =
946 IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect,
947 markDirty ? 0 :
948 D3DLOCK_NO_DIRTY_UPDATE);
949 if (FAILED(result)) {
950 D3D_SetError("LockRect()", result);
951 return -1;
952 }
953 *pixels = locked.pBits;
954 *pitch = locked.Pitch;
955 return 0;
956 }
957 }
958
959 static void
960 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
961 {
962 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
963
964 if (data->yuv) {
965 SDL_SW_UnlockYUVTexture(data->yuv);
966 UpdateYUVTextureData(texture);
967 } else {
968 IDirect3DTexture9_UnlockRect(data->texture, 0);
969 }
970 }
971
972 static void
973 D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
974 const SDL_Rect * rects)
975 {
976 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
977 RECT d3drect;
978 int i;
979
980 for (i = 0; i < numrects; ++i) {
981 const SDL_Rect *rect = &rects[i];
982
983 d3drect.left = rect->x;
984 d3drect.right = rect->x + rect->w;
985 d3drect.top = rect->y;
986 d3drect.bottom = rect->y + rect->h;
987
988 IDirect3DTexture9_AddDirtyRect(data->texture, &d3drect);
989 }
990 }
991
992 static void
993 D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
994 {
995 switch (blendMode) {
996 case SDL_BLENDMODE_NONE:
997 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
998 FALSE);
999 break;
1000 case SDL_BLENDMODE_MASK:
1001 case SDL_BLENDMODE_BLEND:
1002 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
1003 TRUE);
1004 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
1005 D3DBLEND_SRCALPHA);
1006 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
1007 D3DBLEND_INVSRCALPHA);
1008 break;
1009 case SDL_BLENDMODE_ADD:
1010 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
1011 TRUE);
1012 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
1013 D3DBLEND_SRCALPHA);
1014 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
1015 D3DBLEND_ONE);
1016 break;
1017 case SDL_BLENDMODE_MOD:
1018 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
1019 TRUE);
1020 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
1021 D3DBLEND_ZERO);
1022 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
1023 D3DBLEND_SRCCOLOR);
1024 break;
1025 }
1026 }
1027
1028 static int
1029 D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
1030 int count)
1031 {
1032 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1033 DWORD color;
1034 Vertex *vertices;
1035 int i;
1036 HRESULT result;
1037
1038 if (data->beginScene) {
1039 IDirect3DDevice9_BeginScene(data->device);
1040 data->beginScene = SDL_FALSE;
1041 }
1042
1043 D3D_SetBlendMode(data, renderer->blendMode);
1044
1045 result =
1046 IDirect3DDevice9_SetTexture(data->device, 0,
1047 (IDirect3DBaseTexture9 *) 0);
1048 if (FAILED(result)) {
1049 D3D_SetError("SetTexture()", result);
1050 return -1;
1051 }
1052
1053 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1054
1055 vertices = SDL_stack_alloc(Vertex, count);
1056 for (i = 0; i < count; ++i) {
1057 vertices[i].x = (float) points[i].x;
1058 vertices[i].y = (float) points[i].y;
1059 vertices[i].z = 0.0f;
1060 vertices[i].rhw = 1.0f;
1061 vertices[i].color = color;
1062 vertices[i].u = 0.0f;
1063 vertices[i].v = 0.0f;
1064 }
1065 result =
1066 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
1067 vertices, sizeof(*vertices));
1068 SDL_stack_free(vertices);
1069 if (FAILED(result)) {
1070 D3D_SetError("DrawPrimitiveUP()", result);
1071 return -1;
1072 }
1073 return 0;
1074 }
1075
1076 static int
1077 D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
1078 int count)
1079 {
1080 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1081 DWORD color;
1082 Vertex *vertices;
1083 int i;
1084 HRESULT result;
1085
1086 if (data->beginScene) {
1087 IDirect3DDevice9_BeginScene(data->device);
1088 data->beginScene = SDL_FALSE;
1089 }
1090
1091 D3D_SetBlendMode(data, renderer->blendMode);
1092
1093 result =
1094 IDirect3DDevice9_SetTexture(data->device, 0,
1095 (IDirect3DBaseTexture9 *) 0);
1096 if (FAILED(result)) {
1097 D3D_SetError("SetTexture()", result);
1098 return -1;
1099 }
1100
1101 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1102
1103 vertices = SDL_stack_alloc(Vertex, count);
1104 for (i = 0; i < count; ++i) {
1105 vertices[i].x = (float) points[i].x;
1106 vertices[i].y = (float) points[i].y;
1107 vertices[i].z = 0.0f;
1108 vertices[i].rhw = 1.0f;
1109 vertices[i].color = color;
1110 vertices[i].u = 0.0f;
1111 vertices[i].v = 0.0f;
1112 }
1113 result =
1114 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
1115 vertices, sizeof(*vertices));
1116
1117 /* DirectX 9 has the same line rasterization semantics as GDI,
1118 so we need to close the endpoint of the line */
1119 if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1120 vertices[0].x = (float) points[count-1].x;
1121 vertices[0].y = (float) points[count-1].y;
1122 result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
1123 }
1124
1125 SDL_stack_free(vertices);
1126 if (FAILED(result)) {
1127 D3D_SetError("DrawPrimitiveUP()", result);
1128 return -1;
1129 }
1130 return 0;
1131 }
1132
1133 static int
1134 D3D_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
1135 int count)
1136 {
1137 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1138 DWORD color;
1139 int i;
1140 Vertex vertices[5];
1141 HRESULT result;
1142
1143 if (data->beginScene) {
1144 IDirect3DDevice9_BeginScene(data->device);
1145 data->beginScene = SDL_FALSE;
1146 }
1147
1148 D3D_SetBlendMode(data, renderer->blendMode);
1149
1150 result =
1151 IDirect3DDevice9_SetTexture(data->device, 0,
1152 (IDirect3DBaseTexture9 *) 0);
1153 if (FAILED(result)) {
1154 D3D_SetError("SetTexture()", result);
1155 return -1;
1156 }
1157
1158 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1159
1160 for (i = 0; i < SDL_arraysize(vertices); ++i) {
1161 vertices[i].z = 0.0f;
1162 vertices[i].rhw = 1.0f;
1163 vertices[i].color = color;
1164 vertices[i].u = 0.0f;
1165 vertices[i].v = 0.0f;
1166 }
1167
1168 for (i = 0; i < count; ++i) {
1169 const SDL_Rect *rect = rects[i];
1170
1171 vertices[0].x = (float) rect->x;
1172 vertices[0].y = (float) rect->y;
1173
1174 vertices[1].x = (float) rect->x+rect->w-1;
1175 vertices[1].y = (float) rect->y;
1176
1177 vertices[2].x = (float) rect->x+rect->w-1;
1178 vertices[2].y = (float) rect->y+rect->h-1;
1179
1180 vertices[3].x = (float) rect->x;
1181 vertices[3].y = (float) rect->y+rect->h-1;
1182
1183 vertices[4].x = (float) rect->x;
1184 vertices[4].y = (float) rect->y;
1185
1186 result =
1187 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, 4,
1188 vertices, sizeof(*vertices));
1189
1190 if (FAILED(result)) {
1191 D3D_SetError("DrawPrimitiveUP()", result);
1192 return -1;
1193 }
1194 }
1195 return 0;
1196 }
1197
1198 static int
1199 D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
1200 int count)
1201 {
1202 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1203 DWORD color;
1204 int i;
1205 float minx, miny, maxx, maxy;
1206 Vertex vertices[4];
1207 HRESULT result;
1208
1209 if (data->beginScene) {
1210 IDirect3DDevice9_BeginScene(data->device);
1211 data->beginScene = SDL_FALSE;
1212 }
1213
1214 D3D_SetBlendMode(data, renderer->blendMode);
1215
1216 result =
1217 IDirect3DDevice9_SetTexture(data->device, 0,
1218 (IDirect3DBaseTexture9 *) 0);
1219 if (FAILED(result)) {
1220 D3D_SetError("SetTexture()", result);
1221 return -1;
1222 }
1223
1224 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
1225
1226 for (i = 0; i < count; ++i) {
1227 const SDL_Rect *rect = rects[i];
1228
1229 minx = (float) rect->x;
1230 miny = (float) rect->y;
1231 maxx = (float) rect->x + rect->w;
1232 maxy = (float) rect->y + rect->h;
1233
1234 vertices[0].x = minx;
1235 vertices[0].y = miny;
1236 vertices[0].z = 0.0f;
1237 vertices[0].rhw = 1.0f;
1238 vertices[0].color = color;
1239 vertices[0].u = 0.0f;
1240 vertices[0].v = 0.0f;
1241
1242 vertices[1].x = maxx;
1243 vertices[1].y = miny;
1244 vertices[1].z = 0.0f;
1245 vertices[1].rhw = 1.0f;
1246 vertices[1].color = color;
1247 vertices[1].u = 0.0f;
1248 vertices[1].v = 0.0f;
1249
1250 vertices[2].x = maxx;
1251 vertices[2].y = maxy;
1252 vertices[2].z = 0.0f;
1253 vertices[2].rhw = 1.0f;
1254 vertices[2].color = color;
1255 vertices[2].u = 0.0f;
1256 vertices[2].v = 0.0f;
1257
1258 vertices[3].x = minx;
1259 vertices[3].y = maxy;
1260 vertices[3].z = 0.0f;
1261 vertices[3].rhw = 1.0f;
1262 vertices[3].color = color;
1263 vertices[3].u = 0.0f;
1264 vertices[3].v = 0.0f;
1265
1266 result =
1267 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
1268 2, vertices, sizeof(*vertices));
1269 if (FAILED(result)) {
1270 D3D_SetError("DrawPrimitiveUP()", result);
1271 return -1;
1272 }
1273 }
1274 return 0;
1275 }
1276
1277 static int
1278 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1279 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
1280 {
1281 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1282 D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
1283 LPDIRECT3DPIXELSHADER9 shader = NULL;
1284 float minx, miny, maxx, maxy;
1285 float minu, maxu, minv, maxv;
1286 DWORD color;
1287 Vertex vertices[4];
1288 HRESULT result;
1289
1290 if (data->beginScene) {
1291 IDirect3DDevice9_BeginScene(data->device);
1292 data->beginScene = SDL_FALSE;
1293 }
1294
1295 minx = (float) dstrect->x - 0.5f;
1296 miny = (float) dstrect->y - 0.5f;
1297 maxx = (float) dstrect->x + dstrect->w - 0.5f;
1298 maxy = (float) dstrect->y + dstrect->h - 0.5f;
1299
1300 minu = (float) srcrect->x / texture->w;
1301 maxu = (float) (srcrect->x + srcrect->w) / texture->w;
1302 minv = (float) srcrect->y / texture->h;
1303 maxv = (float) (srcrect->y + srcrect->h) / texture->h;
1304
1305 color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
1306
1307 vertices[0].x = minx;
1308 vertices[0].y = miny;
1309 vertices[0].z = 0.0f;
1310 vertices[0].rhw = 1.0f;
1311 vertices[0].color = color;
1312 vertices[0].u = minu;
1313 vertices[0].v = minv;
1314
1315 vertices[1].x = maxx;
1316 vertices[1].y = miny;
1317 vertices[1].z = 0.0f;
1318 vertices[1].rhw = 1.0f;
1319 vertices[1].color = color;
1320 vertices[1].u = maxu;
1321 vertices[1].v = minv;
1322
1323 vertices[2].x = maxx;
1324 vertices[2].y = maxy;
1325 vertices[2].z = 0.0f;
1326 vertices[2].rhw = 1.0f;
1327 vertices[2].color = color;
1328 vertices[2].u = maxu;
1329 vertices[2].v = maxv;
1330
1331 vertices[3].x = minx;
1332 vertices[3].y = maxy;
1333 vertices[3].z = 0.0f;
1334 vertices[3].rhw = 1.0f;
1335 vertices[3].color = color;
1336 vertices[3].u = minu;
1337 vertices[3].v = maxv;
1338
1339 D3D_SetBlendMode(data, texture->blendMode);
1340
1341 if (texture->blendMode == SDL_BLENDMODE_MASK) {
1342 shader = data->ps_mask;
1343 }
1344
1345 switch (texture->scaleMode) {
1346 case SDL_SCALEMODE_NONE:
1347 case SDL_SCALEMODE_FAST:
1348 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
1349 D3DTEXF_POINT);
1350 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
1351 D3DTEXF_POINT);
1352 break;
1353 case SDL_SCALEMODE_SLOW:
1354 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
1355 D3DTEXF_LINEAR);
1356 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
1357 D3DTEXF_LINEAR);
1358 break;
1359 case SDL_SCALEMODE_BEST:
1360 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
1361 D3DTEXF_GAUSSIANQUAD);
1362 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
1363 D3DTEXF_GAUSSIANQUAD);
1364 break;
1365 }
1366
1367 result =
1368 IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
1369 texturedata->texture);
1370 if (FAILED(result)) {
1371 D3D_SetError("SetTexture()", result);
1372 return -1;
1373 }
1374 if (shader) {
1375 result = IDirect3DDevice9_SetPixelShader(data->device, shader);
1376 if (FAILED(result)) {
1377 D3D_SetError("SetShader()", result);
1378 return -1;
1379 }
1380 }
1381 result =
1382 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
1383 vertices, sizeof(*vertices));
1384 if (FAILED(result)) {
1385 D3D_SetError("DrawPrimitiveUP()", result);
1386 return -1;
1387 }
1388 if (shader) {
1389 result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
1390 if (FAILED(result)) {
1391 D3D_SetError("SetShader()", result);
1392 return -1;
1393 }
1394 }
1395 return 0;
1396 }
1397
1398 static int
1399 D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1400 Uint32 format, void * pixels, int pitch)
1401 {
1402 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1403 SDL_Window *window = renderer->window;
1404 SDL_VideoDisplay *display = window->display;
1405 D3DSURFACE_DESC desc;
1406 LPDIRECT3DSURFACE9 backBuffer;
1407 LPDIRECT3DSURFACE9 surface;
1408 RECT d3drect;
1409 D3DLOCKED_RECT locked;
1410 HRESULT result;
1411
1412 result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
1413 if (FAILED(result)) {
1414 D3D_SetError("GetBackBuffer()", result);
1415 return -1;
1416 }
1417
1418 result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
1419 if (FAILED(result)) {
1420 D3D_SetError("GetDesc()", result);
1421 IDirect3DSurface9_Release(backBuffer);
1422 return -1;
1423 }
1424
1425 result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
1426 if (FAILED(result)) {
1427 D3D_SetError("CreateOffscreenPlainSurface()", result);
1428 IDirect3DSurface9_Release(backBuffer);
1429 return -1;
1430 }
1431
1432 result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
1433 if (FAILED(result)) {
1434 D3D_SetError("GetRenderTargetData()", result);
1435 IDirect3DSurface9_Release(surface);
1436 IDirect3DSurface9_Release(backBuffer);
1437 return -1;
1438 }
1439
1440 d3drect.left = rect->x;
1441 d3drect.right = rect->x + rect->w;
1442 d3drect.top = rect->y;
1443 d3drect.bottom = rect->y + rect->h;
1444
1445 result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
1446 if (FAILED(result)) {
1447 D3D_SetError("LockRect()", result);
1448 IDirect3DSurface9_Release(surface);
1449 IDirect3DSurface9_Release(backBuffer);
1450 return -1;
1451 }
1452
1453 SDL_ConvertPixels(rect->w, rect->h,
1454 display->current_mode.format, locked.pBits, locked.Pitch,
1455 format, pixels, pitch);
1456
1457 IDirect3DSurface9_UnlockRect(surface);
1458
1459 IDirect3DSurface9_Release(surface);
1460 IDirect3DSurface9_Release(backBuffer);
1461
1462 return 0;
1463 }
1464
1465 static int
1466 D3D_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1467 Uint32 format, const void * pixels, int pitch)
1468 {
1469 /* Work in progress */
1470 SDL_Unsupported();
1471 return -1;
1472 }
1473
1474 static void
1475 D3D_RenderPresent(SDL_Renderer * renderer)
1476 {
1477 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1478 HRESULT result;
1479
1480 if (!data->beginScene) {
1481 IDirect3DDevice9_EndScene(data->device);
1482 data->beginScene = SDL_TRUE;
1483 }
1484
1485 result = IDirect3DDevice9_TestCooperativeLevel(data->device);
1486 if (result == D3DERR_DEVICELOST) {
1487 /* We'll reset later */
1488 return;
1489 }
1490 if (result == D3DERR_DEVICENOTRESET) {
1491 D3D_Reset(renderer);
1492 }
1493 result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
1494 if (FAILED(result)) {
1495 D3D_SetError("Present()", result);
1496 }
1497 }
1498
1499 static void
1500 D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1501 {
1502 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1503
1504 if (!data) {
1505 return;
1506 }
1507 if (data->yuv) {
1508 SDL_SW_DestroyYUVTexture(data->yuv);
1509 }
1510 if (data->texture) {
1511 IDirect3DTexture9_Release(data->texture);
1512 }
1513 SDL_free(data);
1514 texture->driverdata = NULL;
1515 }
1516
1517 static void
1518 D3D_DestroyRenderer(SDL_Renderer * renderer)
1519 {
1520 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1521
1522 if (data) {
1523 if (data->device) {
1524 IDirect3DDevice9_Release(data->device);
1525 }
1526 SDL_free(data);
1527 }
1528 SDL_free(renderer);
1529 }
1530
1531 #endif /* SDL_VIDEO_RENDER_D3D */
1532
1533 /* vi: set ts=4 sw=4 expandtab: */