comparison src/render/direct3d/SDL_render_d3d.c @ 5198:bb45ecd958d8

Renamed files for consistency
author Sam Lantinga <slouken@libsdl.org>
date Sat, 05 Feb 2011 12:01:11 -0800
parents src/render/direct3d/SDL_d3drender.c@69f47f2c1856
children 25ffd4e5255c
comparison
equal deleted inserted replaced
5197:69f47f2c1856 5198:bb45ecd958d8
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 "../../core/windows/SDL_windows.h"
27
28 #include "SDL_loadso.h"
29 #include "SDL_syswm.h"
30 #include "../SDL_sysrender.h"
31
32 #if SDL_VIDEO_RENDER_D3D
33 #define D3D_DEBUG_INFO
34 #include <d3d9.h>
35 #endif
36
37 #ifdef ASSEMBLE_SHADER
38 ///////////////////////////////////////////////////////////////////////////
39 // ID3DXBuffer:
40 // ------------
41 // The buffer object is used by D3DX to return arbitrary size data.
42 //
43 // GetBufferPointer -
44 // Returns a pointer to the beginning of the buffer.
45 //
46 // GetBufferSize -
47 // Returns the size of the buffer, in bytes.
48 ///////////////////////////////////////////////////////////////////////////
49
50 typedef interface ID3DXBuffer ID3DXBuffer;
51 typedef interface ID3DXBuffer *LPD3DXBUFFER;
52
53 // {8BA5FB08-5195-40e2-AC58-0D989C3A0102}
54 DEFINE_GUID(IID_ID3DXBuffer,
55 0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2);
56
57 #undef INTERFACE
58 #define INTERFACE ID3DXBuffer
59
60 typedef interface ID3DXBuffer {
61 const struct ID3DXBufferVtbl FAR* lpVtbl;
62 } ID3DXBuffer;
63 typedef const struct ID3DXBufferVtbl ID3DXBufferVtbl;
64 const struct ID3DXBufferVtbl
65 {
66 // IUnknown
67 STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
68 STDMETHOD_(ULONG, AddRef)(THIS) PURE;
69 STDMETHOD_(ULONG, Release)(THIS) PURE;
70
71 // ID3DXBuffer
72 STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
73 STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE;
74 };
75
76 HRESULT WINAPI
77 D3DXAssembleShader(
78 LPCSTR pSrcData,
79 UINT SrcDataLen,
80 CONST LPVOID* pDefines,
81 LPVOID pInclude,
82 DWORD Flags,
83 LPD3DXBUFFER* ppShader,
84 LPD3DXBUFFER* ppErrorMsgs);
85
86 #endif /* ASSEMBLE_SHADER */
87
88
89 /* Direct3D renderer implementation */
90
91 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
92 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
93 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
94 const SDL_Rect * rect, const void *pixels,
95 int pitch);
96 static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
97 const SDL_Rect * rect, void **pixels, int *pitch);
98 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
99 static int D3D_RenderDrawPoints(SDL_Renderer * renderer,
100 const SDL_Point * points, int count);
101 static int D3D_RenderDrawLines(SDL_Renderer * renderer,
102 const SDL_Point * points, int count);
103 static int D3D_RenderFillRects(SDL_Renderer * renderer,
104 const SDL_Rect ** rects, int count);
105 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
106 const SDL_Rect * srcrect, const SDL_Rect * dstrect);
107 static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
108 Uint32 format, void * pixels, int pitch);
109 static void D3D_RenderPresent(SDL_Renderer * renderer);
110 static void D3D_DestroyTexture(SDL_Renderer * renderer,
111 SDL_Texture * texture);
112 static void D3D_DestroyRenderer(SDL_Renderer * renderer);
113
114
115 SDL_RenderDriver D3D_RenderDriver = {
116 D3D_CreateRenderer,
117 {
118 "direct3d",
119 (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
120 1,
121 {SDL_PIXELFORMAT_ARGB8888},
122 0,
123 0}
124 };
125
126 typedef struct
127 {
128 void* d3dDLL;
129 IDirect3D9 *d3d;
130 IDirect3DDevice9 *device;
131 UINT adapter;
132 D3DPRESENT_PARAMETERS pparams;
133 SDL_bool beginScene;
134 } D3D_RenderData;
135
136 typedef struct
137 {
138 IDirect3DTexture9 *texture;
139 } D3D_TextureData;
140
141 typedef struct
142 {
143 float x, y, z;
144 float rhw;
145 DWORD color;
146 float u, v;
147 } Vertex;
148
149 static void
150 D3D_SetError(const char *prefix, HRESULT result)
151 {
152 const char *error;
153
154 switch (result) {
155 case D3DERR_WRONGTEXTUREFORMAT:
156 error = "WRONGTEXTUREFORMAT";
157 break;
158 case D3DERR_UNSUPPORTEDCOLOROPERATION:
159 error = "UNSUPPORTEDCOLOROPERATION";
160 break;
161 case D3DERR_UNSUPPORTEDCOLORARG:
162 error = "UNSUPPORTEDCOLORARG";
163 break;
164 case D3DERR_UNSUPPORTEDALPHAOPERATION:
165 error = "UNSUPPORTEDALPHAOPERATION";
166 break;
167 case D3DERR_UNSUPPORTEDALPHAARG:
168 error = "UNSUPPORTEDALPHAARG";
169 break;
170 case D3DERR_TOOMANYOPERATIONS:
171 error = "TOOMANYOPERATIONS";
172 break;
173 case D3DERR_CONFLICTINGTEXTUREFILTER:
174 error = "CONFLICTINGTEXTUREFILTER";
175 break;
176 case D3DERR_UNSUPPORTEDFACTORVALUE:
177 error = "UNSUPPORTEDFACTORVALUE";
178 break;
179 case D3DERR_CONFLICTINGRENDERSTATE:
180 error = "CONFLICTINGRENDERSTATE";
181 break;
182 case D3DERR_UNSUPPORTEDTEXTUREFILTER:
183 error = "UNSUPPORTEDTEXTUREFILTER";
184 break;
185 case D3DERR_CONFLICTINGTEXTUREPALETTE:
186 error = "CONFLICTINGTEXTUREPALETTE";
187 break;
188 case D3DERR_DRIVERINTERNALERROR:
189 error = "DRIVERINTERNALERROR";
190 break;
191 case D3DERR_NOTFOUND:
192 error = "NOTFOUND";
193 break;
194 case D3DERR_MOREDATA:
195 error = "MOREDATA";
196 break;
197 case D3DERR_DEVICELOST:
198 error = "DEVICELOST";
199 break;
200 case D3DERR_DEVICENOTRESET:
201 error = "DEVICENOTRESET";
202 break;
203 case D3DERR_NOTAVAILABLE:
204 error = "NOTAVAILABLE";
205 break;
206 case D3DERR_OUTOFVIDEOMEMORY:
207 error = "OUTOFVIDEOMEMORY";
208 break;
209 case D3DERR_INVALIDDEVICE:
210 error = "INVALIDDEVICE";
211 break;
212 case D3DERR_INVALIDCALL:
213 error = "INVALIDCALL";
214 break;
215 case D3DERR_DRIVERINVALIDCALL:
216 error = "DRIVERINVALIDCALL";
217 break;
218 case D3DERR_WASSTILLDRAWING:
219 error = "WASSTILLDRAWING";
220 break;
221 default:
222 error = "UNKNOWN";
223 break;
224 }
225 SDL_SetError("%s: %s", prefix, error);
226 }
227
228 static D3DFORMAT
229 PixelFormatToD3DFMT(Uint32 format)
230 {
231 switch (format) {
232 case SDL_PIXELFORMAT_RGB565:
233 return D3DFMT_R5G6B5;
234 case SDL_PIXELFORMAT_RGB888:
235 return D3DFMT_X8R8G8B8;
236 case SDL_PIXELFORMAT_ARGB8888:
237 return D3DFMT_A8R8G8B8;
238 default:
239 return D3DFMT_UNKNOWN;
240 }
241 }
242
243 static Uint32
244 D3DFMTToPixelFormat(D3DFORMAT format)
245 {
246 switch (format) {
247 case D3DFMT_R5G6B5:
248 return SDL_PIXELFORMAT_RGB565;
249 case D3DFMT_X8R8G8B8:
250 return SDL_PIXELFORMAT_RGB888;
251 case D3DFMT_A8R8G8B8:
252 return SDL_PIXELFORMAT_ARGB8888;
253 default:
254 return SDL_PIXELFORMAT_UNKNOWN;
255 }
256 }
257
258 SDL_Renderer *
259 D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
260 {
261 SDL_Renderer *renderer;
262 D3D_RenderData *data;
263 SDL_SysWMinfo windowinfo;
264 HRESULT result;
265 D3DPRESENT_PARAMETERS pparams;
266 IDirect3DSwapChain9 *chain;
267 D3DCAPS9 caps;
268 Uint32 window_flags;
269 int w, h;
270 SDL_DisplayMode fullscreen_mode;
271
272 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
273 if (!renderer) {
274 SDL_OutOfMemory();
275 return NULL;
276 }
277
278 data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data));
279 if (!data) {
280 SDL_free(renderer);
281 SDL_OutOfMemory();
282 return NULL;
283 }
284
285 data->d3dDLL = SDL_LoadObject("D3D9.DLL");
286 if (data->d3dDLL) {
287 IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
288
289 D3DCreate =
290 (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL,
291 "Direct3DCreate9");
292 if (D3DCreate) {
293 data->d3d = D3DCreate(D3D_SDK_VERSION);
294 }
295 if (!data->d3d) {
296 SDL_UnloadObject(data->d3dDLL);
297 data->d3dDLL = NULL;
298 }
299 }
300 if (!data->d3d) {
301 SDL_free(renderer);
302 SDL_free(data);
303 SDL_SetError("Unable to create Direct3D interface");
304 return NULL;
305 }
306
307 renderer->CreateTexture = D3D_CreateTexture;
308 renderer->UpdateTexture = D3D_UpdateTexture;
309 renderer->LockTexture = D3D_LockTexture;
310 renderer->UnlockTexture = D3D_UnlockTexture;
311 renderer->RenderDrawPoints = D3D_RenderDrawPoints;
312 renderer->RenderDrawLines = D3D_RenderDrawLines;
313 renderer->RenderFillRects = D3D_RenderFillRects;
314 renderer->RenderCopy = D3D_RenderCopy;
315 renderer->RenderReadPixels = D3D_RenderReadPixels;
316 renderer->RenderPresent = D3D_RenderPresent;
317 renderer->DestroyTexture = D3D_DestroyTexture;
318 renderer->DestroyRenderer = D3D_DestroyRenderer;
319 renderer->info = D3D_RenderDriver.info;
320 renderer->driverdata = data;
321
322 renderer->info.flags = SDL_RENDERER_ACCELERATED;
323
324 SDL_VERSION(&windowinfo.version);
325 SDL_GetWindowWMInfo(window, &windowinfo);
326
327 window_flags = SDL_GetWindowFlags(window);
328 SDL_GetWindowSize(window, &w, &h);
329 SDL_GetWindowDisplayMode(window, &fullscreen_mode);
330
331 SDL_zero(pparams);
332 pparams.hDeviceWindow = windowinfo.info.win.window;
333 pparams.BackBufferWidth = w;
334 pparams.BackBufferHeight = h;
335 if (window_flags & SDL_WINDOW_FULLSCREEN) {
336 pparams.BackBufferFormat =
337 PixelFormatToD3DFMT(fullscreen_mode.format);
338 } else {
339 pparams.BackBufferFormat = D3DFMT_UNKNOWN;
340 }
341 pparams.BackBufferCount = 1;
342 pparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
343
344 if (window_flags & SDL_WINDOW_FULLSCREEN) {
345 pparams.Windowed = FALSE;
346 pparams.FullScreen_RefreshRateInHz =
347 fullscreen_mode.refresh_rate;
348 } else {
349 pparams.Windowed = TRUE;
350 pparams.FullScreen_RefreshRateInHz = 0;
351 }
352 if (flags & SDL_RENDERER_PRESENTVSYNC) {
353 pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
354 } else {
355 pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
356 }
357
358 /* FIXME: Which adapter? */
359 data->adapter = D3DADAPTER_DEFAULT;
360 IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps);
361
362 result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
363 D3DDEVTYPE_HAL,
364 pparams.hDeviceWindow,
365 (caps.
366 DevCaps &
367 D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
368 D3DCREATE_HARDWARE_VERTEXPROCESSING :
369 D3DCREATE_SOFTWARE_VERTEXPROCESSING,
370 &pparams, &data->device);
371 if (FAILED(result)) {
372 D3D_DestroyRenderer(renderer);
373 D3D_SetError("CreateDevice()", result);
374 return NULL;
375 }
376 data->beginScene = SDL_TRUE;
377
378 /* Get presentation parameters to fill info */
379 result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
380 if (FAILED(result)) {
381 D3D_DestroyRenderer(renderer);
382 D3D_SetError("GetSwapChain()", result);
383 return NULL;
384 }
385 result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams);
386 if (FAILED(result)) {
387 IDirect3DSwapChain9_Release(chain);
388 D3D_DestroyRenderer(renderer);
389 D3D_SetError("GetPresentParameters()", result);
390 return NULL;
391 }
392 IDirect3DSwapChain9_Release(chain);
393 if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) {
394 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
395 }
396 data->pparams = pparams;
397
398 IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
399 renderer->info.max_texture_width = caps.MaxTextureWidth;
400 renderer->info.max_texture_height = caps.MaxTextureHeight;
401
402 /* Set up parameters for rendering */
403 IDirect3DDevice9_SetVertexShader(data->device, NULL);
404 IDirect3DDevice9_SetFVF(data->device,
405 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
406 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE);
407 IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
408 D3DCULL_NONE);
409 IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
410 /* Enable color modulation by diffuse color */
411 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP,
412 D3DTOP_MODULATE);
413 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1,
414 D3DTA_TEXTURE);
415 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2,
416 D3DTA_DIFFUSE);
417 /* Enable alpha modulation by diffuse alpha */
418 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP,
419 D3DTOP_MODULATE);
420 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1,
421 D3DTA_TEXTURE);
422 IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
423 D3DTA_DIFFUSE);
424 /* Disable second texture stage, since we're done */
425 IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
426 D3DTOP_DISABLE);
427 IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP,
428 D3DTOP_DISABLE);
429
430 return renderer;
431 }
432
433 static int
434 D3D_Reset(SDL_Renderer * renderer)
435 {
436 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
437 HRESULT result;
438
439 result = IDirect3DDevice9_Reset(data->device, &data->pparams);
440 if (FAILED(result)) {
441 if (result == D3DERR_DEVICELOST) {
442 /* Don't worry about it, we'll reset later... */
443 return 0;
444 } else {
445 D3D_SetError("Reset()", result);
446 return -1;
447 }
448 }
449 IDirect3DDevice9_SetVertexShader(data->device, NULL);
450 IDirect3DDevice9_SetFVF(data->device,
451 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
452 IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE,
453 D3DCULL_NONE);
454 IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
455 return 0;
456 }
457
458 /* FIXME: This needs to be called... when? */
459 #if 0
460 static int
461 D3D_DisplayModeChanged(SDL_Renderer * renderer)
462 {
463 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
464 SDL_Window *window = renderer->window;
465 SDL_VideoDisplay *display = window->display;
466
467 data->pparams.BackBufferWidth = window->w;
468 data->pparams.BackBufferHeight = window->h;
469 if (window->flags & SDL_WINDOW_FULLSCREEN) {
470 data->pparams.BackBufferFormat =
471 PixelFormatToD3DFMT(window->fullscreen_mode.format);
472 } else {
473 data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;
474 }
475 return D3D_Reset(renderer);
476 }
477 #endif
478
479 static int
480 D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
481 {
482 D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
483 SDL_Window *window = renderer->window;
484 D3DFORMAT display_format = renderdata->pparams.BackBufferFormat;
485 D3D_TextureData *data;
486 D3DPOOL pool;
487 DWORD usage;
488 HRESULT result;
489
490 data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data));
491 if (!data) {
492 SDL_OutOfMemory();
493 return -1;
494 }
495
496 texture->driverdata = data;
497
498 #ifdef USE_DYNAMIC_TEXTURE
499 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
500 pool = D3DPOOL_DEFAULT;
501 usage = D3DUSAGE_DYNAMIC;
502 } else
503 #endif
504 {
505 pool = D3DPOOL_MANAGED;
506 usage = 0;
507 }
508
509 result =
510 IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
511 texture->h, 1, usage,
512 PixelFormatToD3DFMT(texture->format),
513 pool, &data->texture, NULL);
514 if (FAILED(result)) {
515 D3D_SetError("CreateTexture()", result);
516 return -1;
517 }
518
519 return 0;
520 }
521
522 static int
523 D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
524 const SDL_Rect * rect, const void *pixels, int pitch)
525 {
526 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
527 D3D_RenderData *renderdata = (D3D_RenderData *) renderer->driverdata;
528 RECT d3drect;
529 D3DLOCKED_RECT locked;
530 const Uint8 *src;
531 Uint8 *dst;
532 int row, length;
533 HRESULT result;
534
535 #ifdef USE_DYNAMIC_TEXTURE
536 if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
537 rect->x == 0 && rect->y == 0 &&
538 rect->w == texture->w && rect->h == texture->h) {
539 result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
540 } else
541 #endif
542 {
543 d3drect.left = rect->x;
544 d3drect.right = rect->x + rect->w;
545 d3drect.top = rect->y;
546 d3drect.bottom = rect->y + rect->h;
547 result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
548 }
549
550 if (FAILED(result)) {
551 D3D_SetError("LockRect()", result);
552 return -1;
553 }
554
555 src = pixels;
556 dst = locked.pBits;
557 length = rect->w * SDL_BYTESPERPIXEL(texture->format);
558 if (length == pitch && length == locked.Pitch) {
559 SDL_memcpy(dst, src, length*rect->h);
560 } else {
561 for (row = 0; row < rect->h; ++row) {
562 SDL_memcpy(dst, src, length);
563 src += pitch;
564 dst += locked.Pitch;
565 }
566 }
567 IDirect3DTexture9_UnlockRect(data->texture, 0);
568
569 return 0;
570 }
571
572 static int
573 D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
574 const SDL_Rect * rect, void **pixels, int *pitch)
575 {
576 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
577 RECT d3drect;
578 D3DLOCKED_RECT locked;
579 HRESULT result;
580
581 d3drect.left = rect->x;
582 d3drect.right = rect->x + rect->w;
583 d3drect.top = rect->y;
584 d3drect.bottom = rect->y + rect->h;
585
586 result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
587 if (FAILED(result)) {
588 D3D_SetError("LockRect()", result);
589 return -1;
590 }
591 *pixels = locked.pBits;
592 *pitch = locked.Pitch;
593 return 0;
594 }
595
596 static void
597 D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
598 {
599 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
600
601 IDirect3DTexture9_UnlockRect(data->texture, 0);
602 }
603
604 static void
605 D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
606 {
607 switch (blendMode) {
608 case SDL_BLENDMODE_NONE:
609 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
610 FALSE);
611 break;
612 case SDL_BLENDMODE_BLEND:
613 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
614 TRUE);
615 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
616 D3DBLEND_SRCALPHA);
617 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
618 D3DBLEND_INVSRCALPHA);
619 break;
620 case SDL_BLENDMODE_ADD:
621 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
622 TRUE);
623 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
624 D3DBLEND_SRCALPHA);
625 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
626 D3DBLEND_ONE);
627 break;
628 case SDL_BLENDMODE_MOD:
629 IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
630 TRUE);
631 IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
632 D3DBLEND_ZERO);
633 IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
634 D3DBLEND_SRCCOLOR);
635 break;
636 }
637 }
638
639 static int
640 D3D_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
641 int count)
642 {
643 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
644 DWORD color;
645 Vertex *vertices;
646 int i;
647 HRESULT result;
648
649 if (data->beginScene) {
650 IDirect3DDevice9_BeginScene(data->device);
651 data->beginScene = SDL_FALSE;
652 }
653
654 D3D_SetBlendMode(data, renderer->blendMode);
655
656 result =
657 IDirect3DDevice9_SetTexture(data->device, 0,
658 (IDirect3DBaseTexture9 *) 0);
659 if (FAILED(result)) {
660 D3D_SetError("SetTexture()", result);
661 return -1;
662 }
663
664 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
665
666 vertices = SDL_stack_alloc(Vertex, count);
667 for (i = 0; i < count; ++i) {
668 vertices[i].x = (float) points[i].x;
669 vertices[i].y = (float) points[i].y;
670 vertices[i].z = 0.0f;
671 vertices[i].rhw = 1.0f;
672 vertices[i].color = color;
673 vertices[i].u = 0.0f;
674 vertices[i].v = 0.0f;
675 }
676 result =
677 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
678 vertices, sizeof(*vertices));
679 SDL_stack_free(vertices);
680 if (FAILED(result)) {
681 D3D_SetError("DrawPrimitiveUP()", result);
682 return -1;
683 }
684 return 0;
685 }
686
687 static int
688 D3D_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
689 int count)
690 {
691 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
692 DWORD color;
693 Vertex *vertices;
694 int i;
695 HRESULT result;
696
697 if (data->beginScene) {
698 IDirect3DDevice9_BeginScene(data->device);
699 data->beginScene = SDL_FALSE;
700 }
701
702 D3D_SetBlendMode(data, renderer->blendMode);
703
704 result =
705 IDirect3DDevice9_SetTexture(data->device, 0,
706 (IDirect3DBaseTexture9 *) 0);
707 if (FAILED(result)) {
708 D3D_SetError("SetTexture()", result);
709 return -1;
710 }
711
712 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
713
714 vertices = SDL_stack_alloc(Vertex, count);
715 for (i = 0; i < count; ++i) {
716 vertices[i].x = (float) points[i].x;
717 vertices[i].y = (float) points[i].y;
718 vertices[i].z = 0.0f;
719 vertices[i].rhw = 1.0f;
720 vertices[i].color = color;
721 vertices[i].u = 0.0f;
722 vertices[i].v = 0.0f;
723 }
724 result =
725 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count-1,
726 vertices, sizeof(*vertices));
727
728 /* DirectX 9 has the same line rasterization semantics as GDI,
729 so we need to close the endpoint of the line */
730 if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
731 vertices[0].x = (float) points[count-1].x;
732 vertices[0].y = (float) points[count-1].y;
733 result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
734 }
735
736 SDL_stack_free(vertices);
737 if (FAILED(result)) {
738 D3D_SetError("DrawPrimitiveUP()", result);
739 return -1;
740 }
741 return 0;
742 }
743
744 static int
745 D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
746 int count)
747 {
748 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
749 DWORD color;
750 int i;
751 float minx, miny, maxx, maxy;
752 Vertex vertices[4];
753 HRESULT result;
754
755 if (data->beginScene) {
756 IDirect3DDevice9_BeginScene(data->device);
757 data->beginScene = SDL_FALSE;
758 }
759
760 D3D_SetBlendMode(data, renderer->blendMode);
761
762 result =
763 IDirect3DDevice9_SetTexture(data->device, 0,
764 (IDirect3DBaseTexture9 *) 0);
765 if (FAILED(result)) {
766 D3D_SetError("SetTexture()", result);
767 return -1;
768 }
769
770 color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
771
772 for (i = 0; i < count; ++i) {
773 const SDL_Rect *rect = rects[i];
774
775 minx = (float) rect->x;
776 miny = (float) rect->y;
777 maxx = (float) rect->x + rect->w;
778 maxy = (float) rect->y + rect->h;
779
780 vertices[0].x = minx;
781 vertices[0].y = miny;
782 vertices[0].z = 0.0f;
783 vertices[0].rhw = 1.0f;
784 vertices[0].color = color;
785 vertices[0].u = 0.0f;
786 vertices[0].v = 0.0f;
787
788 vertices[1].x = maxx;
789 vertices[1].y = miny;
790 vertices[1].z = 0.0f;
791 vertices[1].rhw = 1.0f;
792 vertices[1].color = color;
793 vertices[1].u = 0.0f;
794 vertices[1].v = 0.0f;
795
796 vertices[2].x = maxx;
797 vertices[2].y = maxy;
798 vertices[2].z = 0.0f;
799 vertices[2].rhw = 1.0f;
800 vertices[2].color = color;
801 vertices[2].u = 0.0f;
802 vertices[2].v = 0.0f;
803
804 vertices[3].x = minx;
805 vertices[3].y = maxy;
806 vertices[3].z = 0.0f;
807 vertices[3].rhw = 1.0f;
808 vertices[3].color = color;
809 vertices[3].u = 0.0f;
810 vertices[3].v = 0.0f;
811
812 result =
813 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
814 2, vertices, sizeof(*vertices));
815 if (FAILED(result)) {
816 D3D_SetError("DrawPrimitiveUP()", result);
817 return -1;
818 }
819 }
820 return 0;
821 }
822
823 static int
824 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
825 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
826 {
827 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
828 D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
829 LPDIRECT3DPIXELSHADER9 shader = NULL;
830 float minx, miny, maxx, maxy;
831 float minu, maxu, minv, maxv;
832 DWORD color;
833 Vertex vertices[4];
834 HRESULT result;
835
836 if (data->beginScene) {
837 IDirect3DDevice9_BeginScene(data->device);
838 data->beginScene = SDL_FALSE;
839 }
840
841 minx = (float) dstrect->x - 0.5f;
842 miny = (float) dstrect->y - 0.5f;
843 maxx = (float) dstrect->x + dstrect->w - 0.5f;
844 maxy = (float) dstrect->y + dstrect->h - 0.5f;
845
846 minu = (float) srcrect->x / texture->w;
847 maxu = (float) (srcrect->x + srcrect->w) / texture->w;
848 minv = (float) srcrect->y / texture->h;
849 maxv = (float) (srcrect->y + srcrect->h) / texture->h;
850
851 color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);
852
853 vertices[0].x = minx;
854 vertices[0].y = miny;
855 vertices[0].z = 0.0f;
856 vertices[0].rhw = 1.0f;
857 vertices[0].color = color;
858 vertices[0].u = minu;
859 vertices[0].v = minv;
860
861 vertices[1].x = maxx;
862 vertices[1].y = miny;
863 vertices[1].z = 0.0f;
864 vertices[1].rhw = 1.0f;
865 vertices[1].color = color;
866 vertices[1].u = maxu;
867 vertices[1].v = minv;
868
869 vertices[2].x = maxx;
870 vertices[2].y = maxy;
871 vertices[2].z = 0.0f;
872 vertices[2].rhw = 1.0f;
873 vertices[2].color = color;
874 vertices[2].u = maxu;
875 vertices[2].v = maxv;
876
877 vertices[3].x = minx;
878 vertices[3].y = maxy;
879 vertices[3].z = 0.0f;
880 vertices[3].rhw = 1.0f;
881 vertices[3].color = color;
882 vertices[3].u = minu;
883 vertices[3].v = maxv;
884
885 D3D_SetBlendMode(data, texture->blendMode);
886
887 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
888 D3DTEXF_LINEAR);
889 IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
890 D3DTEXF_LINEAR);
891
892 result =
893 IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
894 texturedata->texture);
895 if (FAILED(result)) {
896 D3D_SetError("SetTexture()", result);
897 return -1;
898 }
899 if (shader) {
900 result = IDirect3DDevice9_SetPixelShader(data->device, shader);
901 if (FAILED(result)) {
902 D3D_SetError("SetShader()", result);
903 return -1;
904 }
905 }
906 result =
907 IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
908 vertices, sizeof(*vertices));
909 if (FAILED(result)) {
910 D3D_SetError("DrawPrimitiveUP()", result);
911 return -1;
912 }
913 if (shader) {
914 result = IDirect3DDevice9_SetPixelShader(data->device, NULL);
915 if (FAILED(result)) {
916 D3D_SetError("SetShader()", result);
917 return -1;
918 }
919 }
920 return 0;
921 }
922
923 static int
924 D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
925 Uint32 format, void * pixels, int pitch)
926 {
927 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
928 D3DSURFACE_DESC desc;
929 LPDIRECT3DSURFACE9 backBuffer;
930 LPDIRECT3DSURFACE9 surface;
931 RECT d3drect;
932 D3DLOCKED_RECT locked;
933 HRESULT result;
934
935 result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
936 if (FAILED(result)) {
937 D3D_SetError("GetBackBuffer()", result);
938 return -1;
939 }
940
941 result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
942 if (FAILED(result)) {
943 D3D_SetError("GetDesc()", result);
944 IDirect3DSurface9_Release(backBuffer);
945 return -1;
946 }
947
948 result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
949 if (FAILED(result)) {
950 D3D_SetError("CreateOffscreenPlainSurface()", result);
951 IDirect3DSurface9_Release(backBuffer);
952 return -1;
953 }
954
955 result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
956 if (FAILED(result)) {
957 D3D_SetError("GetRenderTargetData()", result);
958 IDirect3DSurface9_Release(surface);
959 IDirect3DSurface9_Release(backBuffer);
960 return -1;
961 }
962
963 d3drect.left = rect->x;
964 d3drect.right = rect->x + rect->w;
965 d3drect.top = rect->y;
966 d3drect.bottom = rect->y + rect->h;
967
968 result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
969 if (FAILED(result)) {
970 D3D_SetError("LockRect()", result);
971 IDirect3DSurface9_Release(surface);
972 IDirect3DSurface9_Release(backBuffer);
973 return -1;
974 }
975
976 SDL_ConvertPixels(rect->w, rect->h,
977 D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
978 format, pixels, pitch);
979
980 IDirect3DSurface9_UnlockRect(surface);
981
982 IDirect3DSurface9_Release(surface);
983 IDirect3DSurface9_Release(backBuffer);
984
985 return 0;
986 }
987
988 static void
989 D3D_RenderPresent(SDL_Renderer * renderer)
990 {
991 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
992 HRESULT result;
993
994 if (!data->beginScene) {
995 IDirect3DDevice9_EndScene(data->device);
996 data->beginScene = SDL_TRUE;
997 }
998
999 result = IDirect3DDevice9_TestCooperativeLevel(data->device);
1000 if (result == D3DERR_DEVICELOST) {
1001 /* We'll reset later */
1002 return;
1003 }
1004 if (result == D3DERR_DEVICENOTRESET) {
1005 D3D_Reset(renderer);
1006 }
1007 result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL);
1008 if (FAILED(result)) {
1009 D3D_SetError("Present()", result);
1010 }
1011 }
1012
1013 static void
1014 D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1015 {
1016 D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
1017
1018 if (!data) {
1019 return;
1020 }
1021 if (data->texture) {
1022 IDirect3DTexture9_Release(data->texture);
1023 }
1024 SDL_free(data);
1025 texture->driverdata = NULL;
1026 }
1027
1028 static void
1029 D3D_DestroyRenderer(SDL_Renderer * renderer)
1030 {
1031 D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
1032
1033 if (data) {
1034 if (data->device) {
1035 IDirect3DDevice9_Release(data->device);
1036 }
1037 if (data->d3d) {
1038 IDirect3D9_Release(data->d3d);
1039 SDL_UnloadObject(data->d3dDLL);
1040 }
1041 SDL_free(data);
1042 }
1043 SDL_free(renderer);
1044 }
1045
1046 #endif /* SDL_VIDEO_RENDER_D3D */
1047
1048 /* vi: set ts=4 sw=4 expandtab: */