Mercurial > sdl-ios-xcode
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: */ |