1 // $Header: x:/prj/tech/libsrc/lgd3d/RCS/texture.c 1.45 1998/04/27 15:00:24 KEVIN Exp $
2 #define WIN32_LEAN_AND_MEAN
22 static const char *hResErrorMsg
= "%s:\nFacility %i, Error %i";
24 #define CheckHResult(hRes, msg) \
25 AssertMsg3(hRes==0, hResErrorMsg, msg, (hRes>>16)&0x7fff, hRes&0xffff)
30 #define mono_printf(x) \
36 #define mono_printf(x)
42 uchar *p_mono = (uchar *)0xb0086; \
49 #define GBitMask15 0x3e0
50 #define GBitMask16 0x7e0
52 D3DMATERIALHANDLE MaterialHandle
[LGD3D_MAX_TEXTURES
];
53 D3DTEXTUREHANDLE TextureHandle
[LGD3D_MAX_TEXTURES
];
54 grs_bitmap
*TdrvBitmap
[LGD3D_MAX_TEXTURES
];
64 typedef struct d3d_cookie
{
75 static DDPIXELFORMAT AlphaTextureFormat
;
76 static DDPIXELFORMAT RGBTextureFormat
;
77 static DDPIXELFORMAT PalTextureFormat
;
78 static LPDDPIXELFORMAT FormatList
[PF_MAX
];
79 static DWORD DeviceSurfaceCaps
;
80 static BOOL texture_RGB
= FALSE
;
81 static BOOL prefer_RGB
= FALSE
;
82 static BOOL using_local
= FALSE
;
83 static BOOL local_available
= FALSE
;
84 static BOOL agp_available
= FALSE
;
86 static BOOL TextureListInited
= FALSE
;
87 static LPD3DITEXTURE Texture
[LGD3D_MAX_TEXTURES
];
88 static LPDIRECTDRAWSURFACE Surface
[LGD3D_MAX_TEXTURES
];
90 static LPD3DIMATERIAL Material
[LGD3D_MAX_TEXTURES
];
92 #define MAX_PALETTES 256
94 static grs_bitmap
*default_bm
= NULL
;
95 static LPDIRECTDRAWPALETTE lpDDPalTexture
[MAX_PALETTES
];
96 static LPDIRECTDRAW lpdd
=NULL
;
97 static LPDIRECTDRAW2 lpdd2
=NULL
;
98 static IWinDisplayDevice
* pWinDisplayDevice
= NULL
;
100 static void CheckSurfaces(sWinDispDevCallbackInfo
*data
);
101 static int callback_id
= 0;
103 static ushort default_alpha_pal
[256];
104 static ushort
*texture_pal
[MAX_PALETTES
];
105 static ushort
*alpha_pal
= NULL
;
106 static uchar
*texture_clut
=NULL
;
107 static DevDesc
*device_desc
;
108 static DWORD texture_caps
;
110 void ShutdownTextureSys(void)
114 if (TextureListInited
) {
120 pWinDisplayDevice
->lpVtbl
->RemoveTaskSwitchCallback(
121 pWinDisplayDevice
, callback_id
);
123 // this is actually redundant since tmgr should take
124 // care of it, but it can't really hurt...
125 for (i
=0; i
<LGD3D_MAX_TEXTURES
; i
++) {
126 SafeRelease(Material
[i
]);
127 SafeRelease(Texture
[i
]);
128 SafeRelease(Surface
[i
]);
132 TextureListInited
= FALSE
;
134 if (default_bm
!= NULL
) {
138 for (i
=0; i
<MAX_PALETTES
; i
++)
140 if (texture_pal
[i
]!=NULL
) {
141 gr_free(texture_pal
[i
]);
142 texture_pal
[i
] = NULL
;
144 SafeRelease(lpDDPalTexture
[i
]);
148 SafeRelease(pWinDisplayDevice
);
151 void lgd3d_set_texture_clut(uchar
*clut
)
155 g_tmgr
->set_clut(clut
);
158 void lgd3d_set_alpha_pal(ushort
*pal
)
163 void lgd3d_texture_set_RGB(bool is_RGB
)
168 void lgd3d_get_texture_bitmask(grs_rgb_bitmask
*bitmask
)
170 if (RGBTextureFormat
.dwFlags
== 0)
171 RGBTextureFormat
.dwRBitMask
=
172 RGBTextureFormat
.dwGBitMask
=
173 RGBTextureFormat
.dwBBitMask
= 0;
175 bitmask
->red
= RGBTextureFormat
.dwRBitMask
;
176 bitmask
->green
= RGBTextureFormat
.dwGBitMask
;
177 bitmask
->blue
= RGBTextureFormat
.dwBBitMask
;
181 static HRESULT
InitMaterial(int tex_id
)
183 D3DMATERIAL d3dMaterial
;
187 AssertMsg((tex_id
>=0)&&(tex_id
<LGD3D_MAX_TEXTURES
), "Texture id out of range");
189 hRes
= lpd3d
->lpVtbl
->CreateMaterial(
197 Material
[tex_id
] = Mat
;
199 ZeroMemory(&d3dMaterial
, sizeof(d3dMaterial
));
200 d3dMaterial
.dwSize
= sizeof(d3dMaterial
);
202 d3dMaterial
.diffuse
.r
= D3DVAL(1.0);
203 d3dMaterial
.diffuse
.g
= D3DVAL(1.0);
204 d3dMaterial
.diffuse
.b
= D3DVAL(1.0);
205 d3dMaterial
.ambient
.r
= D3DVAL(1.0);
206 d3dMaterial
.ambient
.g
= D3DVAL(1.0);
207 d3dMaterial
.ambient
.b
= D3DVAL(1.0);
208 d3dMaterial
.specular
.r
= D3DVAL(0.0);
209 d3dMaterial
.specular
.g
= D3DVAL(0.0);
210 d3dMaterial
.specular
.b
= D3DVAL(0.0);
211 d3dMaterial
.dvPower
= D3DVAL(0.0);
212 d3dMaterial
.hTexture
= TextureHandle
[tex_id
];
213 d3dMaterial
.dwRampSize
= 1UL;
215 hRes
= Mat
->lpVtbl
->SetMaterial(Mat
, &d3dMaterial
);
219 hRes
= Mat
->lpVtbl
->GetHandle(Mat
,
221 &MaterialHandle
[tex_id
]);
230 static HRESULT CALLBACK
EnumTextureFormatsCallback(LPDDSURFACEDESC lpDDSD
, LPVOID lpContext
)
232 DDPIXELFORMAT
*fmt
= &lpDDSD
->ddpfPixelFormat
;
235 if (fmt
->dwFlags
&DDPF_RGB
) {
236 mono_printf(("RGB bits: %i, alpha bits: %i\n", fmt
->dwRGBBitCount
, fmt
->dwAlphaBitDepth
));
237 mono_printf(("bitmasks: A %x, R %x G %x B %x\n",
238 fmt
->dwRGBAlphaBitMask
, fmt
->dwRBitMask
, fmt
->dwGBitMask
, fmt
->dwBBitMask
));
242 // Grab 4444 alpha format...
243 if ((fmt
->dwFlags
&DDPF_RGB
)&&(fmt
->dwRGBBitCount
==16)&&
244 (fmt
->dwRGBAlphaBitMask
== 0xf000)&&
245 (fmt
->dwRBitMask
== 0xf00)&&
246 (fmt
->dwGBitMask
== 0xf0)&&
247 (fmt
->dwBBitMask
== 0xf)) {
248 memcpy(&AlphaTextureFormat
, fmt
, sizeof(AlphaTextureFormat
));
250 // Grab 16 bit no alpha format...
251 else if ((fmt
->dwFlags
== DDPF_RGB
)&&
252 (fmt
->dwRGBBitCount
== 16))
254 if ((fmt
->dwGBitMask
== GBitMask16
) ||
255 (fmt
->dwGBitMask
== GBitMask15
)) {
256 memcpy(&RGBTextureFormat
, fmt
, sizeof(RGBTextureFormat
));
259 // Grab 8 bit palettized format
260 else if (lpDDSD
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) {
261 memcpy(&PalTextureFormat
, &lpDDSD
->ddpfPixelFormat
, sizeof(PalTextureFormat
));
267 #define NONLOCAL_CAPS DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_ALLOCONLOAD
268 #define LOCAL_CAPS DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_ALLOCONLOAD
270 static void EnumTextureFormats(void)
273 D3DDEVICEDESC hal
, hel
;
274 LPDIRECTDRAWSURFACE test_surf
;
278 ZeroMemory(&RGBTextureFormat
, sizeof(RGBTextureFormat
));
279 ZeroMemory(&PalTextureFormat
, sizeof(PalTextureFormat
));
281 hRes
= lpd3dDevice
->lpVtbl
->EnumTextureFormats(lpd3dDevice
, EnumTextureFormatsCallback
, NULL
);
282 CheckHResult(hRes
, "EnumTextureFormats failed");
284 texture_RGB
= prefer_RGB
;
285 FormatList
[PF_GENERIC
] = texture_RGB
? &RGBTextureFormat
: &PalTextureFormat
;
286 if (FormatList
[PF_GENERIC
]->dwFlags
== 0) {
287 texture_RGB
= !texture_RGB
;
288 FormatList
[PF_GENERIC
] = texture_RGB
? &RGBTextureFormat
: &PalTextureFormat
;
289 if (FormatList
[PF_GENERIC
]->dwFlags
== 0)
290 CriticalMsg("Direct3D device does not support 8 bit palettized or 15 or 16 bit RGB textures");
293 FormatList
[PF_RGB
] = &RGBTextureFormat
;
294 FormatList
[PF_ALPHA
] = &AlphaTextureFormat
;
296 mono_printf(("Using %s textures\n",texture_RGB
? "16 bit RGB" : "Palettized"));
298 if (AlphaTextureFormat
.dwFlags
== 0)
299 mono_printf(("no alpha texture format available.\n"));
302 ZeroMemory(&hal
, sizeof(hal
));
303 hal
.dwSize
= sizeof(hal
);
304 ZeroMemory(&hel
, sizeof(hel
));
305 hel
.dwSize
= sizeof(hel
);
307 hRes
= lpd3dDevice
->lpVtbl
->GetCaps(lpd3dDevice
, &hal
, &hel
);
308 CheckHResult(hRes
, "Failed to obtain device caps");
310 AssertMsg(hal
.dwFlags
& D3DDD_DEVCAPS
, "No HAL device!");
312 ZeroMemory(&ddsd
, sizeof(ddsd
));
313 memcpy(&ddsd
.ddpfPixelFormat
, FormatList
[PF_GENERIC
], sizeof(ddsd
.ddpfPixelFormat
));
316 agp_available
= FALSE
;
317 local_available
= FALSE
;
319 if (hal
.dwDevCaps
& D3DDEVCAPS_TEXTURENONLOCALVIDMEM
) {
320 ddsd
.dwSize
= sizeof(DDSURFACEDESC
);
321 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
;
322 ddsd
.ddsCaps
.dwCaps
= NONLOCAL_CAPS
;
323 hRes
= lpdd
->lpVtbl
->CreateSurface(lpdd
, &ddsd
, &test_surf
, NULL
);
324 if ((hRes
== DD_OK
) && (test_surf
!= NULL
)) {
325 SafeRelease(test_surf
);
326 agp_available
= TRUE
;
327 DeviceSurfaceCaps
= NONLOCAL_CAPS
;
328 mono_printf(("nonlocal videomemory textures available.\n"));
332 if (hal
.dwDevCaps
& D3DDEVCAPS_TEXTUREVIDEOMEMORY
) {
333 ddsd
.dwSize
= sizeof(DDSURFACEDESC
);
334 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
;
335 ddsd
.ddsCaps
.dwCaps
= LOCAL_CAPS
;
336 hRes
= lpdd
->lpVtbl
->CreateSurface(lpdd
, &ddsd
, &test_surf
, NULL
);
337 if ((hRes
== DD_OK
) && (test_surf
!= NULL
)) {
338 SafeRelease(test_surf
);
339 local_available
= TRUE
;
340 DeviceSurfaceCaps
= LOCAL_CAPS
;
341 mono_printf(("local videomemory textures available.\n"));
345 if (!(agp_available
||local_available
)) {
346 mono_printf(("No local or nonlocal texture memory! Using system memory textures.\n"));
347 DeviceSurfaceCaps
= DDSCAPS_TEXTURE
| DDSCAPS_SYSTEMMEMORY
| DDSCAPS_ALLOCONLOAD
;
349 using_local
= local_available
;
352 static void GetDirectDraw(void)
356 pWinDisplayDevice
= AppGetObj (IWinDisplayDevice
);
359 IWinDisplayDevice_GetDirectDraw(pWinDisplayDevice
, &lpdd
);
360 AssertMsg(lpdd
!=NULL
, "GetDirectDraw failed");
362 hRes
= lpdd
->lpVtbl
->QueryInterface(lpdd
, &IID_IDirectDraw2
, (LPVOID
*)&lpdd2
);
363 CheckHResult(hRes
, "Query for DirectDraw2 failed");
367 static void SetTexturePalette(int start
, int n
, uchar
*pal
, int slot
)
369 PALETTEENTRY peColorTable
[256];
373 if (lpDDPalTexture
[slot
] == NULL
)
375 hRes
= lpdd
->lpVtbl
->CreatePalette(lpdd
,
376 DDPCAPS_8BIT
| DDPCAPS_ALLOW256
,
378 &lpDDPalTexture
[slot
],
380 CheckHResult(hRes
, "CreatePalette failed.");
383 for (i
= 0; i
< n
; i
++) {
384 peColorTable
[i
].peFlags
= D3DPAL_READONLY
| PC_RESERVED
;
385 peColorTable
[i
].peRed
= pal
[3*i
];
386 peColorTable
[i
].peGreen
= pal
[3*i
+1];
387 peColorTable
[i
].peBlue
= pal
[3*i
+2];
390 hRes
= lpDDPalTexture
[slot
]->lpVtbl
->SetEntries(lpDDPalTexture
[slot
],
391 0, start
, n
, peColorTable
);
393 CheckHResult(hRes
, "SetEntries failed.");
396 void lgd3d_set_pal_slot(uint start
, uint n
, uchar
*pal_data
, int slot
)
398 grs_rgb_bitmask bitmask
;
405 SetTexturePalette(start
, n
, pal_data
, slot
);
409 if (texture_pal
[slot
]==NULL
)
410 texture_pal
[slot
] = (ushort
*)gr_malloc(512);
411 lgd3d_get_texture_bitmask(&bitmask
);
412 gr_make_pal16(start
, n
, texture_pal
[slot
], pal_data
, &bitmask
);
416 void lgd3d_set_pal(uint start
, uint n
, uchar
*pal_data
)
418 lgd3d_set_pal_slot(start
, n
, pal_data
, 0);
421 static int chroma_r
=0;
422 static int chroma_g
=0;
423 static int chroma_b
=0;
424 static DWORD chroma_key
;
426 // values should be 0..255
427 void lgd3d_set_chromakey(int r
, int g
, int b
)
432 if (RGBTextureFormat
.dwRBitMask
== 0x1f) {
438 if (RGBTextureFormat
.dwGBitMask
== GBitMask15
) {
439 chroma_key
+= ((g
>>3)<<5) + ((r
>>3)<<10);
441 chroma_key
+= ((g
>>2)<<5) + ((r
>>3)<<11);
446 static int FindClosestColor(float r
, float g
, float b
)
448 float best
=3*256*256;
449 uchar
*pal
= grd_pal
;
452 for (i
=0; i
<256; i
++) {
453 float test
, dr
, dg
, db
;
458 test
= dr
*dr
+ db
*db
+ dg
*dg
;
464 AssertMsg(color
>=0,"Couldn't fit color.");
468 static void InitDefaultTexture(int size
)
473 bm
= gr_alloc_bitmap(BMT_FLAT8
, 0, size
, size
);
474 c0
= FindClosestColor(180.0, 10.0, 10.0);
475 c1
= FindClosestColor(10.0, 180.0, 10.0);
476 for (i
=0; i
<size
; i
++)
477 for (j
=0; j
<size
; j
++)
478 bm
->bits
[size
*i
+j
] = ((i
+j
)&1) ? c0
:c1
;
483 static void InitTextureList(void)
486 for (i
=0; i
<LGD3D_MAX_TEXTURES
; i
++) {
492 TdrvBitmap
[i
] = NULL
;
494 TextureListInited
= TRUE
;
497 static texture_driver driver
;
499 static void CookInfo(tdrv_texture_info
*info
);
500 static int LoadTexture(tdrv_texture_info
*info
);
501 static int ReloadTexture(tdrv_texture_info
*info
);
502 static void ReleaseTexture(int n
);
503 static void UnloadTexture(int n
);
504 extern void SetTextureId(BOOL t
);
507 static void InitTextureManager(lgd3ds_device_info
*info
)
509 driver
.release_texture
= ReleaseTexture
;
510 driver
.load_texture
= LoadTexture
;
511 driver
.set_texture_id
= SetTextureId
;
512 driver
.unload_texture
= UnloadTexture
;
513 driver
.synchronize
= SynchD3D
;
514 driver
.start_frame
= lgd3d_start_frame
;
515 driver
.end_frame
= lgd3d_end_frame
;
516 driver
.reload_texture
= ReloadTexture
;
517 driver
.cook_info
= CookInfo
;
524 g_tmgr
= get_dopey_texture_manager(&driver
);
528 (info
->flags
& LGD3DF_SPEW
) ? TMGRF_SPEW
:0);
533 void InitTextureSys(lgd3ds_device_info
*info
)
538 Warning(("Texture system already inited.\n"));
543 spew
= ((info
->flags
& LGD3DF_SPEW
) != 0);
545 device_desc
= info
->device_desc
;
546 texture_caps
= device_desc
->dpcTriCaps
.dwTextureCaps
;
548 EnumTextureFormats();
549 for (i
=0; i
<MAX_PALETTES
; i
++)
551 texture_pal
[i
] = NULL
;
552 lpDDPalTexture
[i
] = NULL
;
554 lgd3d_set_pal_slot(0,256,grd_pal
,0);
555 lgd3d_set_alpha_pal(default_alpha_pal
);
556 lgd3d_set_chromakey(chroma_r
, chroma_g
, chroma_b
);
558 pWinDisplayDevice
->lpVtbl
->AddTaskSwitchCallback(
559 pWinDisplayDevice
, CheckSurfaces
);
560 InitDefaultTexture(16);
561 InitTextureManager(info
);
566 /***************************************************************************/
567 /* Loading a grs_bitmap into a system memory surface */
568 /***************************************************************************/
571 * Loads a grs_bitmap into a texture map DD surface of the given format. The
572 * memory flag specifies DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY.
575 static HRESULT
CreateSurface(d3d_cookie cookie
, DDSURFACEDESC
*ddsd
, LPDIRECTDRAWSURFACE
*ppDDS
)
579 LPDIRECTDRAWSURFACE pDDS
;
582 ddrval
= lpdd
->lpVtbl
->CreateSurface(lpdd
, ddsd
, ppDDS
, NULL
);
588 // Bind the palette, if necessary
589 if (ddsd
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) {
590 ddrval
= pDDS
->lpVtbl
->SetPalette(pDDS
, lpDDPalTexture
[cookie
.palette
]);
591 CheckHResult(ddrval
, "SetPalette failed while creating surface.");
596 // Set colorkey, if necessary
597 if (PF_TRANS
& cookie
.flags
) {
598 ck
.dwColorSpaceLowValue
= ckey
;
599 ck
.dwColorSpaceHighValue
= ckey
;
600 ddrval
= pDDS
->lpVtbl
->SetColorKey(pDDS
, DDCKEY_SRCBLT
, &ck
);
601 CheckHResult(ddrval
, "SetColorKey failed while creating surface.");
608 // OK, here are our various specialized blitters
610 static void blit_8to16(tdrv_texture_info
*info
, ushort
*dst
, int drow
, ushort
*pal
)
613 grs_bitmap
*bm
= info
->bm
;
614 uchar
*src
= info
->bits
;
616 for (i
=0; i
<bm
->h
; i
++) {
617 for (j
=0; j
<bm
->w
; j
++)
618 dst
[j
] = pal
[src
[j
]];
624 static void blit_8to16_clut(tdrv_texture_info
*info
, ushort
*dst
, int drow
, ushort
*pal
)
627 grs_bitmap
*bm
= info
->bm
;
628 uchar
*src
= info
->bits
;
630 for (i
=0; i
<bm
->h
; i
++) {
631 for (j
=0; j
<bm
->w
; j
++)
632 dst
[j
] = pal
[texture_clut
[src
[j
]]];
638 static void blit_8to16_scale(tdrv_texture_info
*info
, ushort
*dst
, int drow
, ushort
*pal
)
641 int scale_w
= info
->scale_w
;
642 int scale_h
= info
->scale_h
;
643 int step_w
= 1<<(scale_w
-1);
644 int step_h
= (1<<scale_h
)-1;
645 grs_bitmap
*bm
= info
->bm
;
646 uchar
*src
= info
->bits
;
648 for (i
=0; i
<bm
->h
; i
++) {
651 ulong
*base
= (ulong
*)dst
;
652 for (j
=0; j
<bm
->w
; j
++)
654 ulong c32
= pal
[src
[j
]];
656 for (k
=0; k
<step_w
; k
++)
661 for (j
=0; j
<bm
->w
; j
++)
662 dst
[j
] = pal
[src
[j
]];
664 for (j
=0; j
<step_h
; j
++) {
665 memcpy(dst
+ drow
, dst
, 2*(bm
->w
<<scale_w
));
673 static void blit_8to16_clut_scale(tdrv_texture_info
*info
, ushort
*dst
, int drow
, ushort
*pal
)
676 int scale_w
= info
->scale_w
;
677 int scale_h
= info
->scale_h
;
678 int step_w
= 1<<(scale_w
-1);
679 int step_h
= (1<<scale_h
)-1;
680 grs_bitmap
*bm
= info
->bm
;
681 uchar
*src
= info
->bits
;
683 for (i
=0; i
<bm
->h
; i
++) {
686 ulong
*base
= (ulong
*)dst
;
687 for (j
=0; j
<bm
->w
; j
++)
689 ulong c32
= pal
[texture_clut
[src
[j
]]];
691 for (k
=0; k
<step_w
; k
++)
696 for (j
=0; j
<bm
->w
; j
++)
697 dst
[j
] = pal
[texture_clut
[src
[j
]]];
699 for (j
=0; j
<step_h
; j
++) {
700 memcpy(dst
+ drow
, dst
, 2*(bm
->w
<<scale_w
));
709 static void blit_8to8(tdrv_texture_info
*info
, uchar
*dst
, int drow
)
712 grs_bitmap
*bm
= info
->bm
;
713 uchar
*src
= info
->bits
;
715 for (i
=0; i
<bm
->h
; i
++) {
716 memcpy(dst
, src
, bm
->w
);
722 static void blit_8to8_clut(tdrv_texture_info
*info
, uchar
*dst
, int drow
)
725 grs_bitmap
*bm
= info
->bm
;
726 uchar
*src
= info
->bits
;
728 for (i
=0; i
<bm
->h
; i
++) {
729 for (j
=0; j
<bm
->w
; j
++)
730 dst
[j
] = texture_clut
[src
[j
]];
736 static void blit_8to8_scale(tdrv_texture_info
*info
, uchar
*dst
, int drow
)
739 int scale_w
= info
->scale_w
;
740 int scale_h
= info
->scale_h
;
741 int step_w
= 1<<scale_w
;
742 int step_h
= (1<<scale_h
) - 1;
743 grs_bitmap
*bm
= info
->bm
;
744 uchar
*src
= info
->bits
;
746 for (i
=0; i
<bm
->h
; i
++) {
749 for (j
=0; j
<bm
->w
; j
++) {
751 for (k
=0; k
<step_w
; k
++)
756 memcpy(dst
, src
, bm
->w
);
757 for (j
= 0; j
<step_h
; j
++) {
758 memcpy(dst
+ drow
, dst
, bm
->w
);
766 static void blit_8to8_clut_scale(tdrv_texture_info
*info
, uchar
*dst
, int drow
)
769 int scale_w
= info
->scale_w
;
770 int scale_h
= info
->scale_h
;
771 int step_w
= 1<<scale_w
;
772 int step_h
= (1<<scale_h
) - 1;
773 grs_bitmap
*bm
= info
->bm
;
774 uchar
*src
= info
->bits
;
776 for (i
=0; i
<bm
->h
; i
++) {
778 for (j
=0; j
<bm
->w
; j
++) {
779 uchar c
= texture_clut
[src
[j
]];
780 for (k
=0; k
<step_w
; k
++)
784 for (j
= 0; j
<step_h
; j
++) {
785 memcpy(dst
+ drow
, dst
, bm
->w
);
794 static void blit_16to16(tdrv_texture_info
*info
, ushort
*dst
, int drow
)
797 grs_bitmap
*bm
= info
->bm
;
798 uchar
*src
= info
->bits
;
800 for (i
=0; i
<bm
->h
; i
++) {
801 memcpy(dst
, src
, 2*bm
->w
);
808 static void blit_16to16_scale(tdrv_texture_info
*info
, ushort
*dst
, int drow
)
811 int scale_w
= info
->scale_w
;
812 int scale_h
= info
->scale_h
;
813 int step_w
= 1<<scale_w
;
814 int step_h
= (1<<scale_h
) - 1;
815 grs_bitmap
*bm
= info
->bm
;
816 int srow
= bm
->row
>>1;
817 ushort
*src
= (ushort
*)info
->bits
;
819 for (i
=0; i
<bm
->h
; i
++) {
822 for (j
=0; j
<bm
->w
; j
++) {
824 for (k
=0; k
<step_w
; k
++)
829 memcpy(dst
, src
, 2*bm
->w
);
830 for (j
= 0; j
<step_h
; j
++) {
831 memcpy(dst
+ drow
, dst
, 2*bm
->w
);
840 static void LoadSurface(tdrv_texture_info
*info
, DDSURFACEDESC
*ddsd
)
843 grs_bitmap
*bm
= info
->bm
;
844 int flags
= info
->flags
;
847 if ((texture_clut
!= NULL
) && (bm
->flags
& BMF_TRANS
))
849 zero_save
= texture_clut
[0];
853 if (ddsd
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) {
854 uchar
*dst
= (uchar
*)ddsd
->lpSurface
;
855 if ((info
->scale_w
|info
->scale_h
) != 0)
856 if (texture_clut
!=NULL
)
857 blit_8to8_clut_scale(info
, dst
, ddsd
->lPitch
);
859 blit_8to8_scale(info
, dst
, ddsd
->lPitch
);
861 if (texture_clut
!=NULL
)
862 blit_8to8_clut(info
, dst
, ddsd
->lPitch
);
864 blit_8to8(info
, dst
, ddsd
->lPitch
);
866 ushort
*dst
= (ushort
*)ddsd
->lpSurface
;
867 int drow
= ddsd
->lPitch
/2;
869 if (bm
->type
== BMT_FLAT8
) {
873 pal
= (flags
& TF_ALPHA
) ? alpha_pal
: texture_pal
[bm
->align
];
875 pal
= grd_pal16_list
[0];
877 if (flags
& TF_TRANS
) {
882 AssertMsg(pal
!=NULL
, "Hey! trying to use NULL 16 bit palette to load texture!");
885 if ((info
->scale_w
|info
->scale_h
) != 0)
886 if ((flags
& TF_ALPHA
)||(texture_clut
== NULL
))
887 blit_8to16_scale(info
, dst
, drow
, pal
);
889 blit_8to16_clut_scale(info
, dst
, drow
, pal
);
891 if ((flags
& TF_ALPHA
)||(texture_clut
== NULL
))
892 blit_8to16(info
, dst
, drow
, pal
);
894 blit_8to16_clut(info
, dst
, drow
, pal
);
896 if (flags
& TF_TRANS
)
899 } else { // assume straight 16 to 16
900 if ((info
->scale_w
|info
->scale_h
) != 0)
901 blit_16to16_scale(info
, dst
, drow
);
903 blit_16to16(info
, dst
, drow
);
907 texture_clut
[0] = zero_save
;
910 static void GetAvailableTexMem(DWORD
*local
, DWORD
*agp
)
915 AssertMsg(NULL
!=lpdd2
, "No DirectDraw object!");
918 ddscaps
.dwCaps
= LOCAL_CAPS
;
919 lpdd2
->lpVtbl
->GetAvailableVidMem(lpdd2
, &ddscaps
, &total
, local
);
922 ddscaps
.dwCaps
= NONLOCAL_CAPS
;
923 lpdd2
->lpVtbl
->GetAvailableVidMem(lpdd2
, &ddscaps
, &total
, agp
);
928 static void CookInfo(tdrv_texture_info
*info
)
931 int v
, w
=info
->w
, h
=info
->h
;
935 for (v
=2; v
<=w
; v
+=v
)
939 for (v
=2; v
<=h
; v
+=v
)
944 AssertMsg((info
->h
== (1<<cookie
.hlog
)) && (info
->w
== (1<<cookie
.wlog
)),
945 "hlog/wlog does not match texture width/height");
947 if (info
->flags
& TF_ALPHA
)
948 cookie
.flags
= PF_ALPHA
;
949 else if (info
->bm
->type
== BMT_FLAT16
)
950 cookie
.flags
= PF_RGB
;
952 cookie
.flags
= PF_GENERIC
;
954 if (info
->flags
& TF_TRANS
)
955 cookie
.flags
|= PF_TRANS
;
957 if (info
->bm
->type
== BMT_FLAT8
)
958 cookie
.palette
= info
->bm
->align
;
962 info
->cookie
= cookie
.value
;
966 static int ReloadTexture(tdrv_texture_info
*info
)
968 LPDDPIXELFORMAT pixel_format
;
970 LPDIRECTDRAWSURFACE SysmemSurface
, *pDeviceSurface
;
971 LPD3DITEXTURE SysmemTexture
=NULL
, *pDeviceTexture
;
977 pDeviceTexture
= &Texture
[info
->id
];
978 pDeviceSurface
= &Surface
[info
->id
];
982 cookie
.value
= info
->cookie
;
983 pixel_format
= FormatList
[cookie
.flags
&PF_MASK
];
985 if (pixel_format
->dwFlags
==0)
986 // unsupported texture format
989 // Create a surface of the given format using the dimensions of the grs_bitmap
991 ZeroMemory(&ddsd
, sizeof(ddsd
));
993 ddsd
.dwSize
= sizeof(DDSURFACEDESC
);
994 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
;
995 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
| DDSCAPS_SYSTEMMEMORY
;
996 memcpy(&ddsd
.ddpfPixelFormat
, pixel_format
, sizeof(ddsd
.ddpfPixelFormat
));
997 ddsd
.dwHeight
= info
->h
;
998 ddsd
.dwWidth
= info
->w
;
1002 LastError
= CreateSurface(cookie
, &ddsd
, &SysmemSurface
);
1003 CheckHResult(LastError
, "CreateSurface() failed");
1004 AssertMsg(SysmemSurface
!=NULL
, "NULL SysmemSurface");
1006 LastError
= SysmemSurface
->lpVtbl
->QueryInterface(SysmemSurface
,
1008 (LPVOID
*)&SysmemTexture
);
1010 CheckHResult(LastError
, "Failed to obtain D3D texture interface for sysmem surface");
1012 ddsd
.dwSize
= sizeof(DDSURFACEDESC
);
1013 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PIXELFORMAT
;
1018 if (*pDeviceTexture
== NULL
) {
1019 LPDIRECTDRAWSURFACE DeviceSurface
;
1021 ddsd
.ddsCaps
.dwCaps
= DeviceSurfaceCaps
;
1022 LastError
= CreateSurface(cookie
, &ddsd
, pDeviceSurface
);
1023 if ((LastError
!=DD_OK
) && using_local
&& agp_available
)
1025 mono_printf(("using nonlocal vidmem textures...\n"));
1026 // try AGP textures...
1027 using_local
= FALSE
;
1028 DeviceSurfaceCaps
= NONLOCAL_CAPS
;
1029 ddsd
.ddsCaps
.dwCaps
= DeviceSurfaceCaps
;
1030 LastError
= CreateSurface(cookie
, &ddsd
, pDeviceSurface
);
1033 if (LastError
!=DD_OK
) {
1034 mono_printf(("couldn't load texture: error %i.\n", LastError
&0xffff));
1035 SafeRelease(SysmemTexture
);
1036 SafeRelease(SysmemSurface
);
1037 *pDeviceSurface
= NULL
;
1039 return TDRV_FAILURE
;
1042 DeviceSurface
= *pDeviceSurface
;
1044 #define MEMORY_TYPE_MASK \
1045 (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM|DDSCAPS_NONLOCALVIDMEM)
1047 if ((DeviceSurfaceCaps
&MEMORY_TYPE_MASK
) != (ddsd
.ddsCaps
.dwCaps
&MEMORY_TYPE_MASK
))
1049 "device texture not created in requested memory location\nRequested %x Received %x\n",
1050 DeviceSurfaceCaps
&MEMORY_TYPE_MASK
, ddsd
.ddsCaps
.dwCaps
&MEMORY_TYPE_MASK
));
1053 // Query our device surface for a texture interface
1055 LastError
= DeviceSurface
->lpVtbl
->QueryInterface(DeviceSurface
,
1057 (LPVOID
*)pDeviceTexture
);
1058 CheckHResult(LastError
, "Failed to obtain D3D texture interface for device surface.");
1061 // Load the bitmap into the sysmem surface
1062 LastError
= SysmemSurface
->lpVtbl
->Lock(SysmemSurface
, NULL
, &ddsd
, 0, NULL
);
1063 CheckHResult(LastError
, "Failed to lock sysmem surface.");
1065 LoadSurface(info
, &ddsd
);
1067 LastError
= SysmemSurface
->lpVtbl
->Unlock(SysmemSurface
, NULL
);
1068 CheckHResult(LastError
, "Failed to unlock sysmem surface.");
1070 // Load the sysmem texture into the device texture. During this call, a
1071 // driver could compress or reformat the texture surface and put it in
1075 LastError
= pDeviceTexture
[0]->lpVtbl
->Load(pDeviceTexture
[0], SysmemTexture
);
1076 CheckHResult(LastError
, "Failed to load device texture from sysmem texture.");
1078 // Now we are done with sysmem surface
1081 SafeRelease(SysmemTexture
);
1083 SafeRelease(SysmemSurface
);
1085 TdrvBitmap
[info
->id
] = info
->bm
;
1088 return TDRV_SUCCESS
;
1091 static int doLoad(tdrv_texture_info
*info
)
1097 result
= ReloadTexture(info
);
1098 if (result
!= TDRV_SUCCESS
)
1102 LastError
= Texture
[n
]->lpVtbl
->GetHandle(Texture
[n
], lpd3dDevice
, &TextureHandle
[n
]);
1104 if (LastError
!=DD_OK
) {
1105 mono_printf(("GetTextureHandle failed! facility %i error %i width %i height %i\n",
1106 (LastError
>>16)&0x7fff, LastError
&0xffff, info
->w
, info
->h
));
1107 SafeRelease(Texture
[n
]);
1108 SafeRelease(Surface
[n
]);
1110 return TDRV_FAILURE
;
1113 return TDRV_SUCCESS
;
1117 static int LoadTexture(tdrv_texture_info
*info
)
1120 DWORD local_start
=0, agp_start
=0;
1126 if ((info
->h
< device_desc
->dwMinTextureHeight
) ||
1127 (info
->h
> device_desc
->dwMaxTextureHeight
) ||
1128 (info
->w
< device_desc
->dwMinTextureWidth
) ||
1129 (info
->w
> device_desc
->dwMaxTextureWidth
))
1130 return TDRV_FAILURE
;
1132 if ((texture_caps
& D3DPTEXTURECAPS_SQUAREONLY
) && (info
->w
!= info
->h
)) {
1134 return TDRV_FAILURE
;
1138 local_available
? &local_start
: NULL
,
1139 agp_available
? &agp_start
: NULL
);
1141 if ((local_start
< info
->size
) && using_local
&& agp_available
)
1142 { // switch to agp and try again...
1143 mono_printf(("using nonlocal vidmem textures...\n"));
1145 using_local
= FALSE
;
1146 DeviceSurfaceCaps
= NONLOCAL_CAPS
;
1149 if ((using_local
? local_start
: agp_start
) < info
->size
)
1152 return TDRV_FAILURE
;
1155 AssertMsg((n
>=0)&&(n
<LGD3D_MAX_TEXTURES
), "Texture id out of range");
1157 // These should already be taken care of, but just in case...
1158 SafeRelease(Material
[n
]);
1159 SafeRelease(Texture
[n
]);
1160 SafeRelease(Surface
[n
]);
1162 MaterialHandle
[n
]=0;
1164 result
= doLoad(info
);
1166 if ((result
!= TDRV_SUCCESS
) && using_local
&& agp_available
) {
1167 // switch to AGP and try again...
1168 mono_printf(("using nonlocal vidmem textures...\n"));
1170 using_local
= FALSE
;
1171 DeviceSurfaceCaps
= NONLOCAL_CAPS
;
1172 result
= doLoad(info
);
1175 if (result
!= TDRV_SUCCESS
) {
1182 // calculate load size if requested
1183 if (info
->size
== 0) {
1184 DWORD local_end
, agp_end
;
1188 local_available
? &local_end
: NULL
,
1189 agp_available
? &agp_end
: NULL
);
1191 if (local_available
&& (local_start
> local_end
))
1193 AssertMsg( (!agp_available
)||(agp_start
==agp_end
),
1194 "Texture load modified local and nonlocal vidmem!");
1195 info
->size
= local_start
- local_end
;
1197 AssertMsg(agp_available
&& (agp_start
> agp_end
),
1198 "Texture load took no space!");
1199 info
->size
= agp_start
- agp_end
;
1204 return TDRV_SUCCESS
;
1207 static void CheckSurfaces(sWinDispDevCallbackInfo
*info
)
1209 static void (*chain
)(sWinDispDevCallbackInfo
*);
1212 switch (info
->message
) {
1213 case kWinDispDevCallbackActive
:
1214 for (i
=0; i
<LGD3D_MAX_TEXTURES
; i
++) {
1215 LPDIRECTDRAWSURFACE lpTS
= Surface
[i
];
1216 if ((lpTS
== NULL
)||
1217 (lpTS
->lpVtbl
->IsLost(lpTS
) != DDERR_SURFACELOST
))
1220 VerifyMsg(lpTS
->lpVtbl
->Restore(lpTS
)==DD_OK
, "Could not restore lost surface!");
1221 if (TdrvBitmap
[i
]!=NULL
) {
1222 AssertMsg(g_tmgr
!= NULL
, "Hmmm. Should have a non-NULL texture manager here.");
1223 g_tmgr
->unload_texture(TdrvBitmap
[i
]);
1227 case kWinDispDevCallbackUpdateChain
:
1228 GenericCallbackChainHandler(&callback_id
, (callback_chain_func
**)&chain
, (callback_chain_info
*)info
);
1235 extern void UnsetTextureId(int n
);
1236 // Disconnect texture from bitmap, but don't release texture yet
1237 static void UnloadTexture(int n
)
1239 AssertMsg((n
>=0)&&(n
<LGD3D_MAX_TEXTURES
), "Texture id out of range");
1240 TdrvBitmap
[n
] = NULL
;
1243 static void ReleaseTexture(int n
)
1245 AssertMsg((n
>=0)&&(n
<LGD3D_MAX_TEXTURES
), "Texture id out of range");
1247 Assert(Surface
[n
]!=NULL
, ("texture %i already released\n", n
));
1249 if ((Surface
[n
]!=NULL
) && local_available
&& (!using_local
))
1252 Surface
[n
]->lpVtbl
->GetCaps(Surface
[n
], &ddscaps
);
1253 if (ddscaps
.dwCaps
& DDSCAPS_LOCALVIDMEM
)
1255 mono_printf(("Using Local vidmem textures\n"));
1256 DeviceSurfaceCaps
= LOCAL_CAPS
;
1261 SafeRelease(Material
[n
]);
1262 SafeRelease(Texture
[n
]);
1263 SafeRelease(Surface
[n
]);
1264 MaterialHandle
[n
]=0;
1266 TdrvBitmap
[n
] = NULL
;
1274 lpd3dDevice
->lpVtbl
->SetRenderState(lpd3dDevice
,
1275 D3DRENDERSTATE_FLUSHBATCH
, 0);
1276 CheckHResult(hRes
, "FlushBatch failed");