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