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