blob: af5c6a7bd301679dd81ac36478f74c1b8ba9c0d3 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
34char * TR_NAMES[] = {
35 "TR_OPAQUE",
36 "TR_BITMASK",
37 "TR_TRANSLUCENT"
38};
39
40char * 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 */
58typedef 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
68jint D3DUtils_GetPixelFormatType(DDPIXELFORMAT*lpddpf);
69
70HRESULT 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
86HRESULT CALLBACK
87D3DUtils_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
122HRESULT
123WINAPI 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
150HRESULT
151WINAPI 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
170HRESULT
171D3DUtils_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
183HRESULT
184D3DUtils_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
202jint 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
265void
266D3DUtils_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
360const GUID *
361D3DUtils_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 */
433void
434D3DUtils_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
449void
450D3DUtils_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
464DDrawSurface *
465D3DUtils_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
482DDrawSurface *
483D3DUtils_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
501HRESULT
502D3DUtils_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
537HRESULT
538D3DUtils_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
552HRESULT
553D3DUtils_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
579HRESULT
580D3DUtils_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
591HRESULT
592D3DUtils_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}