void d3d_texture_blit(unsigned pixel_size, LPDIRECT3DTEXTURE tex, D3DLOCKED_RECT *lr, const void *frame, unsigned width, unsigned height, unsigned pitch) { #ifdef _XBOX D3DTexture_LockRect(tex, 0, lr, NULL, D3DLOCK_NOSYSLOCK); #if defined(_XBOX360) D3DSURFACE_DESC desc; tex->GetLevelDesc(0, &desc); XGCopySurface(lr->pBits, lr->Pitch, width, height, desc.Format, NULL, frame, pitch, desc.Format, NULL, 0, 0); #elif defined(_XBOX1) unsigned y; for (y = 0; y < height; y++) { const uint8_t *in = (const uint8_t*)frame + y * pitch; uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; memcpy(out, in, width * pixel_size); } #endif D3DTexture_UnlockRect(tex, 0); #else if (SUCCEEDED(tex->LockRect(0, lr, NULL, D3DLOCK_NOSYSLOCK))) { unsigned y; for (y = 0; y < height; y++) { const uint8_t *in = (const uint8_t*)frame + y * pitch; uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; memcpy(out, in, width * pixel_size); } tex->UnlockRect(0); } #endif }
void d3d_lockrectangle_clear(void *data, LPDIRECT3DTEXTURE tex, unsigned level, D3DLOCKED_RECT *lock_rect, RECT *rect, unsigned rectangle_height, unsigned flags) { #if defined(_XBOX) d3d_video_t *d3d = (d3d_video_t*)data; D3DTexture_LockRect(tex, level, lock_rect, rect, flags); memset(lock_rect->pBits, 0, d3d->tex_h * lock_rect->Pitch); #else if (SUCCEEDED(tex->LockRect(level, lock_rect, rect, flags))) { memset(lock_rect->pBits, level, rectangle_height * lock_rect->Pitch); tex->UnlockRect(0); } #endif }
void d3d_texture_blit(void *data, unsigned pixel_size, LPDIRECT3DTEXTURE tex, D3DLOCKED_RECT *lr, const void *frame, unsigned width, unsigned height, unsigned pitch) { unsigned y; d3d_video_t *d3d = (d3d_video_t*)data; (void)y; if (!d3d) return; #ifdef _XBOX /* Set the texture to NULL so D3D doesn't complain about it being in use... */ d3d_set_texture(d3d->dev, 0, NULL); D3DTexture_LockRect(tex, 0, lr, NULL, D3DLOCK_NOSYSLOCK); #if defined(_XBOX360) D3DSURFACE_DESC desc; tex->GetLevelDesc(0, &desc); XGCopySurface(lr->pBits, lr->Pitch, width, height, desc.Format, NULL, frame, pitch, desc.Format, NULL, 0, 0); #elif defined(_XBOX1) for (y = 0; y < height; y++) { const uint8_t *in = (const uint8_t*)frame + y * pitch; uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; memcpy(out, in, width * d3d->pixel_size); } #endif D3DTexture_UnlockRect(tex, 0); #else if (SUCCEEDED(tex->LockRect(0, lr, NULL, D3DLOCK_NOSYSLOCK))) { for (y = 0; y < height; y++) { const uint8_t *in = (const uint8_t*)frame + y * pitch; uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; memcpy(out, in, width * pixel_size); } tex->UnlockRect(0); } #endif }
void d3d_texture_free(LPDIRECT3DTEXTURE tex) { if (tex) { #if defined(HAVE_D3D9) && !defined(__cplusplus) IDirect3DTexture9_Release(tex); #else tex->Release(); #endif } }
void d3d_unlock_rectangle(LPDIRECT3DTEXTURE tex) { #ifdef _XBOX D3DTexture_UnlockRect(tex, 0); #else #if defined(HAVE_D3D9) && !defined(__cplusplus) IDirect3DSurface9_UnlockRect(tex); #else tex->UnlockRect(0); #endif #endif }
bool d3d_lock_rectangle(LPDIRECT3DTEXTURE tex, unsigned level, D3DLOCKED_RECT *lock_rect, RECT *rect, unsigned rectangle_height, unsigned flags) { #if defined(_XBOX) D3DTexture_LockRect(tex, level, lock_rect, rect, flags); return true; #else if (SUCCEEDED(tex->LockRect(level, lock_rect, rect, flags))) return true; return false; #endif }
bool d3d_lock_rectangle(LPDIRECT3DTEXTURE tex, unsigned level, D3DLOCKED_RECT *lock_rect, RECT *rect, unsigned rectangle_height, unsigned flags) { #if defined(_XBOX) D3DTexture_LockRect(tex, level, lock_rect, rect, flags); #elif defined(HAVE_D3D9) && !defined(__cplusplus) if (IDirect3DSurface9_LockRect(tex, lock_rect, rect, flags) != D3D_OK) return false; #else if (FAILED(tex->LockRect(level, lock_rect, rect, flags))) return false; #endif return true; }
void d3d_texture_blit(unsigned pixel_size, LPDIRECT3DTEXTURE tex, D3DLOCKED_RECT *lr, const void *frame, unsigned width, unsigned height, unsigned pitch) { if (d3d_lock_rectangle(tex, 0, lr, NULL, 0, 0)) { #if defined(_XBOX360) && defined(_XBOX360) D3DSURFACE_DESC desc; tex->GetLevelDesc(0, &desc); XGCopySurface(lr->pBits, lr->Pitch, width, height, desc.Format, NULL, frame, pitch, desc.Format, NULL, 0, 0); #else unsigned y; for (y = 0; y < height; y++) { const uint8_t *in = (const uint8_t*)frame + y * pitch; uint8_t *out = (uint8_t*)lr->pBits + y * lr->Pitch; memcpy(out, in, width * pixel_size); } #endif d3d_unlock_rectangle(tex); } }
void d3d_texture_free(LPDIRECT3DTEXTURE tex) { if (tex) tex->Release(); tex = NULL; }
void d3d_unlock_rectangle(LPDIRECT3DTEXTURE tex) { #ifndef _XBOX tex->UnlockRect(0); #endif }
static bool TextureCompressQDM(LPDIRECT3DTEXTURE *base, LPDIRECT3DTEXTURE *norm, int minlevel) { LPDIRECT3DTEXTURE baset; LPDIRECT3DTEXTURE normt; RESOURCEINFO based, baseo; RESOURCEINFO normd, normo; TextureInfoLevel(*base, baseo, 0); TextureInfoLevel(*norm, normo, 0); #if 0 /* Converts a height map into a normal map. The (x,y,z) * components of each normal are mapped to the (r,g,b) * channels of the output texture. */ HRESULT D3DXComputeNormalMap( __out LPDIRECT3DTEXTURE pTexture, __in LPDIRECT3DTEXTURE pSrcTexture, __in const PALETTEENTRY *pSrcPalette, __in DWORD Flags, __in DWORD Channel, __in FLOAT Amplitude ); #endif /* they have to have the same dimension */ if ((baseo.Width != normo.Width ) || (baseo.Height != normo.Height)) return false; /* convert to ARGB8 (TODO: support at least the 16bit formats as well) */ if ((baseo.Format != TEXFMT_A8B8G8R8) && baseo.Format = TEXFMT_A8R8G8B8, !TextureConvert(baseo, base, false)) return false; if ((normo.Format != TEXFMT_A8B8G8R8) && normo.Format = TEXFMT_A8R8G8B8, !TextureConvert(normo, norm, true)) return false; /* create the textures */ int levels = TextureCalcMip(baseo.Width, baseo.Height, minlevel); int flags = squish::kColourIterativeClusterFit | squish::kBtc3; #ifdef DX11 ULONG *bases; ULONG *norms; DWORD basel = 1; DWORD norml = 1; DWORD level = max(basel, norml); #else /* create the textures */ pD3DDevice->CreateTexture(baseo.Width, baseo.Height, levels, 0, D3DFMT_DXT5, D3DPOOL_SYSTEMMEM, &baset, NULL); pD3DDevice->CreateTexture(normo.Width, normo.Height, levels, 0, D3DFMT_DXT5, D3DPOOL_SYSTEMMEM, &normt, NULL); /* damit */ if (!baset || !normt) { if (baset) baset->Release(); if (normt) normt->Release(); return false; } ULONG bPch, *bases = TextureLock(*base, &bPch, 0); ULONG nPch, *norms = TextureLock(*norm, &nPch, 0); DWORD basel = baset->GetLevelCount(); DWORD norml = normt->GetLevelCount(); DWORD level = max(basel, norml); #endif for (unsigned int l = 0; l < level; l++) { /* square dimension of this surface-level */ /* square area of this surface-level */ int lv = (1 << l); int av = lv * lv; TextureInfoLevel(baset, based, l); TextureInfoLevel(normt, normd, l); ULONG sPch, *baser = TextureLock(baset, l, &sPch, true); ULONG nPch, *normr = TextureLock(normt, l, &nPch, true); ULONG *sBase = (ULONG *)bases; ULONG *sNorm = (ULONG *)norms; ULONG *dBase = (ULONG *)baser; ULONG *dNorm = (ULONG *)normr; /* loop over 4x4-blocks of this level (DXT5) */ for (unsigned int y = 0; y < based.Height; y += TY) { if (!(y & 0x3F)) { // logrf("line processed %d/%d of level %d/%d\r", y, based.Height, l, level); // PollProgress(); } for (unsigned int x = 0; x < based.Width; x += TX) { UTYPE bBase[2][TY][TX]; ULONG bNorm[2][TY][TX]; type fBase[2][TY][TX][DIM]; float fNorm[2][TY][TX][DIM]; /* generate this level's 4x4-block from the original surface */ for (int ly = 0; ly < TY; ly += 1) for (int lx = 0; lx < TX; lx += 1) { type bs[DIM] = {0}; int yl = ((y + ly) << l); /*ng ns[DIM] = {0*/ int xl = ((x + lx) << l); float nn[DIM] = {0.0f}; /* access all pixels this level's 4x4-block represents in * the full dimension original surface (high quality mip-mapping) */ for (int oy = 0; oy < lv; oy += 1) for (int ox = 0; ox < lv; ox += 1) { /* assume seamless tiling: wrap pixels around */ int posx = (xl + ox) % baseo.Width; int posy = (yl + oy) % baseo.Height; ULONG &b = sBase[(posy * sPch) + posx]; ULONG &n = sNorm[(posy * nPch) + posx]; /* transfer heightmap into the normal-map (overwrite) */ if (LODed) n = (n & 0x00FFFFFF) + (b & 0xFF000000); { static const f<TCOMPRESS_RGBH> fmt; Accu(bs, b); } { static const f<TCOMPRESS_XYZD> fmt; Accu(nn, n); } // AccuRGBM<ACCUMODE_LINEAR>(bs, b, level, l, colorgamma); // += and max #if defined(NORMALS_INTEGER) // AccuXYZD<ACCUMODE_SCALE >(ns, n, level, l, NORMALS_SCALEBYLEVEL); // += #else // AccuXYZD<ACCUMODE_SCALE >(nn, n, level, l, NORMALS_SCALEBYLEVEL); // += #endif } /* build average of each channel */ { const int format = TCOMPRESS_RGBH; Norm(fBase[0][ly][lx], bs, av, levels, l); } { const int format = TCOMPRESS_XYZD; Norm(fNorm[0][ly][lx], nn, av, levels, l); } // NormRGBM<TRGTMODE_CODING_RGB >(fBase[0][ly][lx], bs, av, colorgammainv); #if defined(NORMALS_INTEGER) // NormXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE>(fNorm[0][ly][lx], ns, av); #else // NormXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE>(fNorm[0][ly][lx], nn, av); #endif } type br[DIM] = {0}; /*ng nr[DIM] = {0*/ float rn[DIM] = {0.0f}; /* analyze this level's 4x4-block */ for (int ly = 0; ly < TY; ly += 1) for (int lx = 0; lx < TX; lx += 1) { { const int format = TCOMPRESS_RGBH; Look(fBase[0][ly][lx], br); } { const int format = TCOMPRESS_XYZD; Look(fNorm[0][ly][lx], rn); } // LookRGBH<TRGTMODE_CODING_RGB >(fBase[0][ly][lx], br); #if defined(NORMALS_INTEGER) // LookXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE>(fNorm[0][ly][lx], nr); #else // LookXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE>(fNorm[0][ly][lx], rn); #endif } /* generate this level's 4x4-block from the original surface */ for (int ly = 0; ly < TY; ly += 1) for (int lx = 0; lx < TX; lx += 1) { /* build average of each channel an join */ UTYPE b; ULONG n; { const int format = TCOMPRESS_RGBH; Code(fBase[0][ly][lx], br, (TCOMPRESS_CHANNELS(format) + (TCOMPRESS_GREYS (format) ? 2 : 0)) == 2 ? 8 : (TCOMPRESS_SWIZZL (format) ? 6 : 5)); } { const int format = TCOMPRESS_XYZD; Code(fNorm[0][ly][lx], rn, (TCOMPRESS_CHANNELS(format) + (TCOMPRESS_GREYS (format) ? 2 : 0)) == 2 ? 8 : (TCOMPRESS_SWIZZL (format) ? 6 : 5)); } { const int format = TCOMPRESS_RGBH; b = Join(fBase[0][ly][lx], br); } { const int format = TCOMPRESS_XYZD; n = Join(fNorm[0][ly][lx], rn); } // CodeRGBH<TRGTMODE_CODING_RGB >(fBase[0][ly][lx], br); #if defined(NORMALS_INTEGER) // CodeXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE, TCOMPRESS_SWIZZL(format) ? 6 : 5>(fNorm[0][ly][lx], nr); #else // CodeXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE, TCOMPRESS_SWIZZL(format) ? 6 : 5>(fNorm[0][ly][lx], rn); #endif // b = JoinRGBH<TRGTMODE_CODING_RGB >(fBase[0][ly][lx], br); #if defined(NORMALS_INTEGER) // n = JoinXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE>(fNorm[0][ly][lx], nr); #else // n = JoinXYZD<TRGTMODE_CODING_DXDYdZt | TRGTNORM_CUBESPACE>(fNorm[0][ly][lx], rn); #endif /* write the result ABGR */ bBase[0][ly][lx] = b; bNorm[0][ly][lx] = n; } /* compress to DXT5 */ #if 0 stb_compress_dxt_block((unsigned char *)dBase, (unsigned char *)bBase[0], true, STB_DXT_DITHER | STB_DXT_HIGHQUAL); stb_compress_dxt_block((unsigned char *)dNorm, (unsigned char *)bNorm[0], true, STB_DXT_NORMAL | STB_DXT_HIGHQUAL); #else squish::Compress((unsigned char *)bBase[0], dBase, flags + squish::kColourMetricPerceptual); squish::Compress((unsigned char *)bNorm[0], dNorm, flags + squish::kColourMetricUniform); #endif /* advance pointer of compressed blocks */ dBase += (128 / 32); dNorm += (128 / 32); #if 0 for (int ly = 0; ly < TY; ly += 1) for (int lx = 0; lx < TX; lx += 1) { dBase[((y + ly) * bPch) + (x + lx)] = bBase[0][ly][lx]; dNorm[((y + ly) * nPch) + (x + lx)] = bNorm[0][ly][lx]; } #endif } } TextureUnlock(baset, l); TextureUnlock(normt, l); } TextureUnlock((*base), 0); TextureUnlock((*norm), 0); (*base)->Release(); (*norm)->Release(); (*base) = baset; (*norm) = normt; return true; }