1 /* |
|
2 * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 |
|
27 #include "ddrawUtils.h" |
|
28 #include "D3DUtils.h" |
|
29 #include "D3DSurfaceData.h" |
|
30 |
|
31 #ifdef DEBUG |
|
32 // These strings must be in the same order as pixel |
|
33 // formats in D3DSurfaceData.java |
|
34 char * TR_NAMES[] = { |
|
35 "TR_OPAQUE", |
|
36 "TR_BITMASK", |
|
37 "TR_TRANSLUCENT" |
|
38 }; |
|
39 |
|
40 char * PF_NAMES[] = { |
|
41 "PF_INVALID" , |
|
42 "PF_INT_ARGB" , |
|
43 "PF_INT_RGB" , |
|
44 "PF_INT_RGBX", |
|
45 "PF_INT_BGR" , |
|
46 "PF_USHORT_565_RGB" , |
|
47 "PF_USHORT_555_RGB" , |
|
48 "PF_USHORT_555_RGBX" , |
|
49 "PF_INT_ARGB_PRE" , |
|
50 "PF_USHORT_4444_ARGB" |
|
51 }; |
|
52 #endif // DEBUG |
|
53 |
|
54 /** |
|
55 * This structure could be used when searching for a pixel |
|
56 * format with preferred bit depth. |
|
57 */ |
|
58 typedef struct { |
|
59 // Pointer to a DDPIXELFORMAT structure where the found pixel |
|
60 // format will be copied to |
|
61 DDPIXELFORMAT *pddpf; |
|
62 // If TRUE, the search was successful, FALSE otherwise |
|
63 BOOL bFoundFormat; |
|
64 // Preferred bit depth |
|
65 int preferredDepth; |
|
66 } PixelFormatSearchStruct; |
|
67 |
|
68 jint D3DUtils_GetPixelFormatType(DDPIXELFORMAT*lpddpf); |
|
69 |
|
70 HRESULT WINAPI EnumAlphaTextureFormatsCallback(DDPIXELFORMAT* pddpf, |
|
71 VOID* pContext ) |
|
72 { |
|
73 J2dTraceLn(J2D_TRACE_VERBOSE, "EnumAlphaTextureFormatsCallback"); |
|
74 DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext; |
|
75 |
|
76 // Looking for a 8-bit luminance texture (and probably not alpha-luminance) |
|
77 if((pddpf->dwFlags & DDPF_ALPHA) && (pddpf->dwAlphaBitDepth == 8)) |
|
78 { |
|
79 memcpy(pddpfOut, pddpf, sizeof(DDPIXELFORMAT)); |
|
80 return D3DENUMRET_CANCEL; |
|
81 } |
|
82 |
|
83 return D3DENUMRET_OK; |
|
84 } |
|
85 |
|
86 HRESULT CALLBACK |
|
87 D3DUtils_TextureSearchCallback(DDPIXELFORMAT *lpddpf, |
|
88 void *param) |
|
89 { |
|
90 J2dTraceLn(J2D_TRACE_VERBOSE, "D3DUtils_TextureSearchCallback"); |
|
91 jint pfType = D3DUtils_GetPixelFormatType(lpddpf); |
|
92 if (pfType == PF_INVALID) { |
|
93 return DDENUMRET_OK; |
|
94 } |
|
95 |
|
96 DWORD dwAlphaBitCount = 0; |
|
97 if (lpddpf->dwFlags & DDPF_ALPHAPIXELS) { |
|
98 DWORD dwMask = lpddpf->dwRGBAlphaBitMask; |
|
99 while( dwMask ) { |
|
100 dwMask = dwMask & ( dwMask - 1 ); |
|
101 dwAlphaBitCount++; |
|
102 } |
|
103 } |
|
104 |
|
105 DWORD dwRGBBitCount = lpddpf->dwRGBBitCount; |
|
106 WORD wDepthIndex = D3D_DEPTH_IDX(dwRGBBitCount); |
|
107 WORD wTransparencyIndex = |
|
108 dwAlphaBitCount > 0 ? TR_TRANSLUCENT_IDX : TR_OPAQUE_IDX; |
|
109 |
|
110 D3DTextureTable *table = (D3DTextureTable*)param; |
|
111 D3DTextureTableCell *cell = &(*table)[wTransparencyIndex][wDepthIndex]; |
|
112 if (cell->pfType == PF_INVALID || pfType < cell->pfType) { |
|
113 // set only if it wasn't set or if current pfType is better than |
|
114 // the one found previously: it's better to use 565 than 555 |
|
115 memcpy(&cell->pddpf, lpddpf, sizeof(DDPIXELFORMAT)); |
|
116 cell->pfType = pfType; |
|
117 } |
|
118 // continue for all pixel formats |
|
119 return DDENUMRET_OK; |
|
120 } |
|
121 |
|
122 HRESULT |
|
123 WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT* pddpf, |
|
124 VOID* pContext ) |
|
125 { |
|
126 J2dTraceLn(J2D_TRACE_VERBOSE, "EnumZBufferFormatsCallback"); |
|
127 PixelFormatSearchStruct *ppfss = (PixelFormatSearchStruct*)pContext; |
|
128 DDPIXELFORMAT* pddpfOut = ppfss->pddpf; |
|
129 |
|
130 // if found a format with the exact depth, return it |
|
131 if (pddpf->dwZBufferBitDepth == (DWORD)ppfss->preferredDepth) { |
|
132 ppfss->bFoundFormat = TRUE; |
|
133 memcpy(pddpfOut, pddpf, sizeof(DDPIXELFORMAT)); |
|
134 return D3DENUMRET_CANCEL; |
|
135 } |
|
136 // If a format with exact depth can't be found, look for the best |
|
137 // available, preferring those with the lowest bit depth to save |
|
138 // video memory. Also, prefer formats with no stencil bits. |
|
139 if (!ppfss->bFoundFormat || |
|
140 (pddpfOut->dwZBufferBitDepth > pddpf->dwZBufferBitDepth && |
|
141 !(pddpf->dwFlags & DDPF_STENCILBUFFER))) |
|
142 { |
|
143 ppfss->bFoundFormat = TRUE; |
|
144 memcpy(pddpfOut, pddpf, sizeof(DDPIXELFORMAT)); |
|
145 } |
|
146 |
|
147 return D3DENUMRET_OK; |
|
148 } |
|
149 |
|
150 HRESULT |
|
151 WINAPI DeviceEnumCallback(LPSTR strDesc, LPSTR strName, |
|
152 LPD3DDEVICEDESC7 pDesc, |
|
153 LPVOID pParentInfo) |
|
154 { |
|
155 J2dTraceLn(J2D_TRACE_VERBOSE, "DeviceEnumCallback"); |
|
156 DEVICES_INFO *devinfo = (DEVICES_INFO*)pParentInfo; |
|
157 |
|
158 if (pDesc->deviceGUID == IID_IDirect3DHALDevice) { |
|
159 devinfo->pGUIDs[HAL_IDX] = &IID_IDirect3DHALDevice; |
|
160 } else if (pDesc->deviceGUID == IID_IDirect3DTnLHalDevice) { |
|
161 devinfo->pGUIDs[TNL_IDX] = &IID_IDirect3DTnLHalDevice; |
|
162 } else if (pDesc->deviceGUID == IID_IDirect3DRGBDevice) { |
|
163 devinfo->pGUIDs[RGB_IDX] = &IID_IDirect3DRGBDevice; |
|
164 } else if (pDesc->deviceGUID == IID_IDirect3DRefDevice) { |
|
165 devinfo->pGUIDs[REF_IDX] = &IID_IDirect3DRefDevice; |
|
166 } |
|
167 return D3DENUMRET_OK; |
|
168 } |
|
169 |
|
170 HRESULT |
|
171 D3DUtils_FindMaskTileTextureFormat(IDirect3DDevice7 *d3dDevice, |
|
172 DDPIXELFORMAT* pddpf) |
|
173 { |
|
174 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_FindMaskTileTextureFormat"); |
|
175 d3dDevice->EnumTextureFormats(EnumAlphaTextureFormatsCallback, |
|
176 (void*)pddpf); |
|
177 if (pddpf->dwAlphaBitDepth == 8) { |
|
178 return D3D_OK; |
|
179 } |
|
180 return DDERR_GENERIC; |
|
181 } |
|
182 |
|
183 HRESULT |
|
184 D3DUtils_FindDepthBufferFormat(IDirect3D7 *d3dObject, |
|
185 int preferredDepth, |
|
186 DDPIXELFORMAT* pddpf, |
|
187 const GUID *pDeviceGUID) |
|
188 { |
|
189 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_FindDepthBufferFormat"); |
|
190 PixelFormatSearchStruct pfss; |
|
191 pfss.pddpf = pddpf; |
|
192 pfss.bFoundFormat = FALSE; |
|
193 pfss.preferredDepth = preferredDepth; |
|
194 |
|
195 d3dObject->EnumZBufferFormats(*pDeviceGUID, |
|
196 EnumZBufferFormatsCallback, |
|
197 (void*)&pfss); |
|
198 |
|
199 return pfss.bFoundFormat ? D3D_OK : DDERR_GENERIC; |
|
200 } |
|
201 |
|
202 jint D3DUtils_GetPixelFormatType(DDPIXELFORMAT*lpddpf) |
|
203 { |
|
204 J2dTraceLn(J2D_TRACE_VERBOSE, "D3DUtils_GetPixelFormatType"); |
|
205 |
|
206 if (lpddpf == NULL) return PF_INVALID; |
|
207 |
|
208 DWORD dwFlags = lpddpf->dwFlags; |
|
209 // skip weird formats |
|
210 if (lpddpf->dwRGBBitCount < 16 || |
|
211 dwFlags & DDPF_ALPHA || dwFlags & DDPF_ZBUFFER || |
|
212 dwFlags & DDPF_ZPIXELS || dwFlags & DDPF_LUMINANCE || |
|
213 dwFlags & DDPF_FOURCC || dwFlags & DDPF_STENCILBUFFER || |
|
214 dwFlags & DDPF_BUMPLUMINANCE || dwFlags & DDPF_BUMPDUDV) |
|
215 { |
|
216 return PF_INVALID; |
|
217 } |
|
218 |
|
219 jint pfType = PF_INVALID; |
|
220 DWORD aMask = lpddpf->dwRGBAlphaBitMask; |
|
221 DWORD rMask = lpddpf->dwRBitMask; |
|
222 DWORD gMask = lpddpf->dwGBitMask; |
|
223 DWORD bMask = lpddpf->dwBBitMask; |
|
224 |
|
225 if (rMask == 0x0000f800 && |
|
226 gMask == 0x000007e0 && |
|
227 bMask == 0x0000001f && |
|
228 aMask == 0x00000000) |
|
229 { |
|
230 pfType = PF_USHORT_565_RGB; |
|
231 } else if (rMask == 0x00007C00 && |
|
232 gMask == 0x000003E0 && |
|
233 bMask == 0x0000001f && |
|
234 aMask == 0x00000000) |
|
235 { |
|
236 pfType = PF_USHORT_555_RGB; |
|
237 } else if (rMask == 0x00000f00 && |
|
238 gMask == 0x000000f0 && |
|
239 bMask == 0x0000000f && |
|
240 aMask == 0x0000f000) |
|
241 { |
|
242 // REMIND: we currently don't support this |
|
243 // pixel format, since we don't have the loops for a |
|
244 // premultiplied version of it. So we'll just use INT_ARGB |
|
245 // for now |
|
246 pfType = PF_INVALID; |
|
247 // pfType = PF_USHORT_4444_ARGB; |
|
248 } else if (rMask == 0x00ff0000 && |
|
249 gMask == 0x0000ff00 && |
|
250 bMask == 0x000000ff) |
|
251 { |
|
252 if (lpddpf->dwRGBBitCount == 32) { |
|
253 pfType = (dwFlags & DDPF_ALPHAPIXELS) ? |
|
254 PF_INT_ARGB : PF_INT_RGB; |
|
255 } else { |
|
256 // We currently don't support this format. |
|
257 // pfType = PF_3BYTE_BGR; |
|
258 pfType = PF_INVALID; |
|
259 } |
|
260 } |
|
261 |
|
262 return pfType; |
|
263 } |
|
264 |
|
265 void |
|
266 D3DUtils_SetupTextureFormats(IDirect3DDevice7 *d3dDevice, |
|
267 D3DTextureTable &table) |
|
268 { |
|
269 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_SetupTextureFormats"); |
|
270 if (d3dDevice == NULL || table == NULL) { |
|
271 return; |
|
272 } |
|
273 |
|
274 ZeroMemory(table, sizeof(D3DTextureTable)); |
|
275 int t; |
|
276 for (t = TR_OPAQUE_IDX; t < TR_MAX_IDX; t++) { |
|
277 for (int d = DEPTH16_IDX; d < DEPTH_MAX_IDX; d++) { |
|
278 table[t][d].pfType = PF_INVALID; |
|
279 } |
|
280 } |
|
281 d3dDevice->EnumTextureFormats(D3DUtils_TextureSearchCallback, table); |
|
282 |
|
283 // We've retrieved the pixel formats for this device. The matrix may |
|
284 // look something like this, depending on the formats the device supports: |
|
285 // Transparency/Depth Depth 16 Depth 24 Depth 32 |
|
286 // ------------------------------------------------------------------------ |
|
287 // TR_OPAQUE PF_USHORT_565_RGB PF_INVALID PF_INT_RGB |
|
288 // TR_BITMASK PF_INVALID PF_INVALID PF_INVALID |
|
289 // TR_TRANSLUCENT PF_INVALID PF_INVALID PF_INT_ARGB |
|
290 |
|
291 |
|
292 // we'll be using translucent pixel formats for bitmask images |
|
293 // for now, this may change later |
|
294 memcpy(&table[TR_BITMASK_IDX], &table[TR_TRANSLUCENT_IDX], |
|
295 sizeof(D3DTextureTableCell[DEPTH_MAX_IDX])); |
|
296 // Transparency/Depth Depth 16 Depth 24 Depth 32 |
|
297 // ------------------------------------------------------------------------ |
|
298 // TR_OPAQUE PF_USHORT_565_RGB PF_INVALID PF_INT_RGB |
|
299 // TR_BITMASK PF_INVALID PF_INVALID PF_INT_ARGB |
|
300 // TR_TRANSLUCENT PF_INVALID PF_INVALID PF_INT_ARGB |
|
301 |
|
302 // REMIND: crude force |
|
303 // Find substitutes for pixel formats which we didn't find. |
|
304 // For example, if we didn't find a 24-bit format, 32-bit will be |
|
305 // a first choice for substitution. But if it wasn't found either, |
|
306 // then use 16-bit format |
|
307 D3DTextureTableCell *cell16, *cell24, *cell32; |
|
308 for (t = TR_OPAQUE_IDX; t < TR_MAX_IDX; t++) { |
|
309 cell16 = &table[t][DEPTH16_IDX]; |
|
310 cell24 = &table[t][DEPTH24_IDX]; |
|
311 cell32 = &table[t][DEPTH32_IDX]; |
|
312 if (cell32->pfType == PF_INVALID) { |
|
313 if (cell24->pfType != PF_INVALID) { |
|
314 memcpy(cell32, cell24, sizeof(D3DTextureTableCell)); |
|
315 } else if (cell16->pfType != PF_INVALID) { |
|
316 memcpy(cell32, cell16, sizeof(D3DTextureTableCell)); |
|
317 } else { |
|
318 // no valid pixel formats for this transparency |
|
319 // type were found |
|
320 continue; |
|
321 } |
|
322 } |
|
323 // now we know that 32-bit is valid |
|
324 if (cell24->pfType == PF_INVALID) { |
|
325 // use 32-bit format as a substitution for 24-bit |
|
326 memcpy(cell24, cell32, sizeof(D3DTextureTableCell)); |
|
327 } |
|
328 // now we know that 32- and 24-bit are valid |
|
329 if (cell16->pfType == PF_INVALID) { |
|
330 // use 24-bit format as a substitution for 16-bit |
|
331 memcpy(cell16, cell24, sizeof(D3DTextureTableCell)); |
|
332 } |
|
333 } |
|
334 // After this loop the matrix may look something like this: |
|
335 // Transparency/Depth Depth 16 Depth 24 Depth 32 |
|
336 // ------------------------------------------------------------------------ |
|
337 // TR_OPAQUE PF_USHORT_565_RGB PF_INT_RGB PF_INT_RGB |
|
338 // TR_BITMASK PF_INT_ARGB PF_INT_ARGB PF_INT_ARGB |
|
339 // TR_TRANSLUCENT PF_INT_ARGB PF_INT_ARGB PF_INT_ARGB |
|
340 |
|
341 #ifdef DEBUG |
|
342 // Print out the matrix (should look something like the comment above) |
|
343 J2dTraceLn1(J2D_TRACE_INFO, |
|
344 "Texutre formats table for device %x", d3dDevice); |
|
345 J2dTraceLn(J2D_TRACE_INFO, "Transparency/Depth Depth 16 "\ |
|
346 "Depth 24 Depth 32"); |
|
347 J2dTraceLn(J2D_TRACE_INFO, "-------------------------------------------"\ |
|
348 "----------------------------"); |
|
349 for (t = TR_OPAQUE_IDX; t < TR_MAX_IDX; t++) { |
|
350 J2dTrace1(J2D_TRACE_INFO, "%15s", TR_NAMES[t]); |
|
351 for (int d = DEPTH16_IDX; d < DEPTH_MAX_IDX; d++) { |
|
352 J2dTrace1(J2D_TRACE_INFO, "%20s", |
|
353 PF_NAMES[table[t][d].pfType]); |
|
354 } |
|
355 J2dTrace(J2D_TRACE_INFO, "\n"); |
|
356 } |
|
357 #endif // DEBUG |
|
358 } |
|
359 |
|
360 const GUID * |
|
361 D3DUtils_SelectDeviceGUID(IDirect3D7 *d3dObject) |
|
362 { |
|
363 static char * RASTERIZER_NAMES[] = { |
|
364 "TNL", "HAL", "REFERENCE", "RGB" |
|
365 }; |
|
366 // try to use TnL rasterizer by default |
|
367 int defIndex = TNL_IDX; |
|
368 |
|
369 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_SelectDeviceGUID"); |
|
370 // unless a different one was requested |
|
371 char *pRasterizer = getenv("J2D_D3D_RASTERIZER"); |
|
372 if (pRasterizer != NULL) { |
|
373 if (strncmp(pRasterizer, "ref", 3) == 0) { |
|
374 defIndex = REF_IDX; |
|
375 } else if (strncmp(pRasterizer, "rgb", 3) == 0) { |
|
376 defIndex = RGB_IDX; |
|
377 } else if (strncmp(pRasterizer, "hal", 3) == 0) { |
|
378 defIndex = HAL_IDX; |
|
379 } else if (strncmp(pRasterizer, "tnl", 3) == 0) { |
|
380 defIndex = TNL_IDX; |
|
381 } |
|
382 J2dTraceLn1(J2D_TRACE_VERBOSE, |
|
383 " rasterizer requested: %s", |
|
384 RASTERIZER_NAMES[defIndex]); |
|
385 } |
|
386 |
|
387 DEVICES_INFO devInfo; |
|
388 memset(&devInfo, 0, sizeof(devInfo)); |
|
389 HRESULT res; |
|
390 if (FAILED(res = d3dObject->EnumDevices(DeviceEnumCallback, |
|
391 (VOID*)&devInfo))) |
|
392 { |
|
393 DebugPrintDirectDrawError(res, "D3DUtils_SelectDeviceGUID: "\ |
|
394 "EnumDevices failed"); |
|
395 return NULL; |
|
396 } |
|
397 |
|
398 // return requested rasterizer's guid if it's present |
|
399 if (devInfo.pGUIDs[defIndex] != NULL) { |
|
400 J2dRlsTraceLn1(J2D_TRACE_VERBOSE, |
|
401 "D3DUtils_SelectDeviceGUID: using %s rasterizer", |
|
402 RASTERIZER_NAMES[defIndex]); |
|
403 return devInfo.pGUIDs[defIndex]; |
|
404 } |
|
405 // if not, try to find one, starting with the best available |
|
406 defIndex = TNL_IDX; |
|
407 do { |
|
408 if (devInfo.pGUIDs[defIndex] != NULL) { |
|
409 J2dRlsTraceLn1(J2D_TRACE_VERBOSE, |
|
410 "D3DUtils_SelectDeviceGUID: using %s rasterizer", |
|
411 RASTERIZER_NAMES[defIndex]); |
|
412 return devInfo.pGUIDs[defIndex]; |
|
413 } |
|
414 // While we could use the rgb and ref rasterizers if tnl and |
|
415 // hal aren't present, it's not practical for performance purposes. |
|
416 // so we just leave an opportunity to force them. |
|
417 } while (++defIndex < REF_IDX /*DEV_IDX_MAX*/); |
|
418 |
|
419 |
|
420 J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
421 "D3DUtils_SelectDeviceGUID: "\ |
|
422 "No Accelerated Rasterizers Found"); |
|
423 return NULL; |
|
424 } |
|
425 |
|
426 |
|
427 /* |
|
428 * This function sets passed matrix to be a custom left-hand off-center |
|
429 * orthogonal matrix. The output is identical to D3DX's function call |
|
430 * D3DXMatrixOrthoOffCenterLH((D3DXMATRIX*)&tx, |
|
431 * 0.0, width, height, 0.0, -1.0, 1.0); |
|
432 */ |
|
433 void |
|
434 D3DUtils_SetOrthoMatrixOffCenterLH(D3DMATRIX *m, |
|
435 float width, float height) |
|
436 { |
|
437 DASSERT((m != NULL) && (width > 0.0f) && (height > 0.0f)); |
|
438 memset(m, 0, sizeof(D3DMATRIX)); |
|
439 m->_11 = 2.0f/width; |
|
440 m->_22 = -2.0f/height; |
|
441 m->_33 = 0.5f; |
|
442 m->_44 = 1.0f; |
|
443 |
|
444 m->_41 = -1.0f; |
|
445 m->_42 = 1.0f; |
|
446 m->_43 = 0.5f; |
|
447 } |
|
448 |
|
449 void |
|
450 D3DUtils_SetIdentityMatrix(D3DMATRIX *m, BOOL adjust) |
|
451 { |
|
452 DASSERT(m != NULL); |
|
453 m->_12 = m->_13 = m->_14 = m->_21 = m->_23 = m->_24 = 0.0f; |
|
454 m->_31 = m->_32 = m->_34 = m->_43 = 0.0f; |
|
455 m->_11 = m->_22 = m->_33 = m->_44 = 1.0f; |
|
456 if (adjust) { |
|
457 // This is required for proper texel alignment |
|
458 m->_41 = m->_42 = -0.5f; |
|
459 } else { |
|
460 m->_41 = m->_42 = 0.0f; |
|
461 } |
|
462 } |
|
463 |
|
464 DDrawSurface * |
|
465 D3DUtils_CreatePlainSurface(JNIEnv *env, |
|
466 DDraw *ddObject, |
|
467 D3DContext *d3dContext, |
|
468 int w, int h) |
|
469 { |
|
470 DXSurface *dxSurface; |
|
471 jint pType; |
|
472 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CreatePlainSurface"); |
|
473 if (FAILED(d3dContext->CreateSurface(env, w, h, 32, |
|
474 TR_OPAQUE, D3D_PLAIN_SURFACE, |
|
475 &dxSurface, &pType))) |
|
476 { |
|
477 return NULL; |
|
478 } |
|
479 return new DDrawSurface(ddObject, dxSurface); |
|
480 } |
|
481 |
|
482 DDrawSurface * |
|
483 D3DUtils_CreateTexture(JNIEnv *env, |
|
484 DDraw *ddObject, |
|
485 D3DContext *d3dContext, |
|
486 int transparency, |
|
487 int w, int h) |
|
488 { |
|
489 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CreateTexture"); |
|
490 DXSurface *dxSurface; |
|
491 jint pType; |
|
492 if (FAILED(d3dContext->CreateSurface(env, w, h, 32, |
|
493 transparency, D3D_TEXTURE_SURFACE, |
|
494 &dxSurface, &pType))) |
|
495 { |
|
496 return NULL; |
|
497 } |
|
498 return new DDrawSurface(ddObject, dxSurface); |
|
499 } |
|
500 |
|
501 HRESULT |
|
502 D3DUtils_UploadIntImageToXRGBTexture(DDrawSurface *lpTexture, |
|
503 int *pSrc, int width, int height) |
|
504 { |
|
505 HRESULT res; |
|
506 int texW = lpTexture->GetDXSurface()->GetWidth(); |
|
507 int texH = lpTexture->GetDXSurface()->GetHeight(); |
|
508 int srcStride = width * 4; |
|
509 |
|
510 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_UploadIntImageToXRGBTexture"); |
|
511 if (width > texW) { |
|
512 width = texW; |
|
513 } |
|
514 if (height > texH) { |
|
515 height = texH; |
|
516 } |
|
517 |
|
518 SurfaceDataRasInfo rasInfo; |
|
519 if (SUCCEEDED(res = lpTexture->Lock(NULL, &rasInfo, |
|
520 DDLOCK_WAIT|DDLOCK_NOSYSLOCK, NULL))) |
|
521 { |
|
522 void *pDstPixels = rasInfo.rasBase; |
|
523 void *pSrcPixels = (void*)pSrc; |
|
524 |
|
525 // REMIND: clear the dest first |
|
526 memset(pDstPixels, 0, texH * rasInfo.scanStride); |
|
527 do { |
|
528 memcpy(pDstPixels, pSrcPixels, width * 4); |
|
529 pSrcPixels = PtrAddBytes(pSrcPixels, srcStride); |
|
530 pDstPixels = PtrAddBytes(pDstPixels, rasInfo.scanStride); |
|
531 } while (--height > 0); |
|
532 res = lpTexture->Unlock(NULL); |
|
533 } |
|
534 return res; |
|
535 } |
|
536 |
|
537 HRESULT |
|
538 D3DUtils_CheckD3DCaps(LPD3DDEVICEDESC7 lpDesc7) |
|
539 { |
|
540 // The device must support fast rasterization |
|
541 static DWORD dwDevCaps = |
|
542 (D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_HWRASTERIZATION); |
|
543 BOOL vt = lpDesc7->dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX; |
|
544 BOOL rz = lpDesc7->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION; |
|
545 |
|
546 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckD3DCaps"); |
|
547 return (lpDesc7->dwDevCaps & dwDevCaps) ? |
|
548 D3D_OK : |
|
549 DDERR_GENERIC; |
|
550 } |
|
551 |
|
552 HRESULT |
|
553 D3DUtils_CheckTextureCaps(LPD3DDEVICEDESC7 lpDesc7) |
|
554 { |
|
555 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckTextureCaps"); |
|
556 // REMIND: we should really check both Tri and Lin caps, |
|
557 // but hopefully we won't be using line strips soon |
|
558 LPD3DPRIMCAPS lpDpcTriCaps = &lpDesc7->dpcTriCaps; |
|
559 // Filtering requirements |
|
560 static DWORD dwFilterCaps = |
|
561 (D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_NEAREST); |
|
562 // Check for caps used for alpha compositing (implementation of |
|
563 // Porter-Duff rules) |
|
564 static DWORD dwBlendCaps = |
|
565 (D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | |
|
566 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | |
|
567 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA); |
|
568 |
|
569 if ((lpDesc7->dwTextureOpCaps & D3DTEXOPCAPS_MODULATE) && |
|
570 (lpDpcTriCaps->dwTextureFilterCaps & dwFilterCaps) && |
|
571 (lpDpcTriCaps->dwSrcBlendCaps & dwBlendCaps) && |
|
572 (lpDpcTriCaps->dwDestBlendCaps & dwBlendCaps)) |
|
573 { |
|
574 return D3D_OK; |
|
575 } |
|
576 return DDERR_GENERIC; |
|
577 } |
|
578 |
|
579 HRESULT |
|
580 D3DUtils_CheckDeviceCaps(LPD3DDEVICEDESC7 lpDesc7) { |
|
581 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckDeviceCaps"); |
|
582 if (SUCCEEDED(D3DUtils_CheckD3DCaps(lpDesc7)) && |
|
583 SUCCEEDED(D3DUtils_CheckTextureCaps(lpDesc7)) && |
|
584 SUCCEEDED(D3DUtils_CheckDepthCaps(lpDesc7))) |
|
585 { |
|
586 return D3D_OK; |
|
587 } |
|
588 return DDERR_GENERIC; |
|
589 } |
|
590 |
|
591 HRESULT |
|
592 D3DUtils_CheckDepthCaps(LPD3DDEVICEDESC7 lpDesc7) |
|
593 { |
|
594 J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckDepthCaps"); |
|
595 // Check for required depth-buffer operations |
|
596 // (see D3DContext::SetClip() for more info). |
|
597 static DWORD dwZCmpCaps = (D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_LESS); |
|
598 // D3DPMISCCAPS_MASKZ capability allows enabling/disabling |
|
599 // depth buffer updates. |
|
600 if ((lpDesc7->dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKZ) && |
|
601 (lpDesc7->dpcTriCaps.dwZCmpCaps & dwZCmpCaps)) |
|
602 { |
|
603 return D3D_OK; |
|
604 } |
|
605 return DDERR_GENERIC; |
|
606 } |
|