implement copy_texture

This commit is contained in:
cxgeorge 2002-09-12 23:39:29 +00:00
parent e9857b36b9
commit 72e396f06d
2 changed files with 36 additions and 296 deletions

View File

@ -397,7 +397,7 @@ read_vertex_shader(string &filename) {
hr = scrn.pD3DDevice->CreateVertexShader((DWORD*)ShaderDeclHeader, hr = scrn.pD3DDevice->CreateVertexShader((DWORD*)ShaderDeclHeader,
(DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes), (DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes),
&hShader, UsageFlags); &hShader, UsageFlags);
if (FAILED(hr)) { if(FAILED(hr)) {
dxgsg_cat.error() << "CreateVertexShader failed for '"<< filename << "' " << D3DERRORSTRING(hr); dxgsg_cat.error() << "CreateVertexShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
hShader=NULL; hShader=NULL;
} }
@ -3237,68 +3237,50 @@ release_texture(TextureContext *tc) {
delete gtc; delete gtc;
} }
#if 1 // copies current display region in framebuffer to the texture
void DXGraphicsStateGuardian::
copy_texture(TextureContext *tc, const DisplayRegion *dr) {
dxgsg_cat.fatal() << "DX copy_texture unimplemented!!!";
}
#else
static int logs[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
4096, 0};
// This function returns the smallest power of two greater than or
// equal to x.
static int binary_log_cap(const int x) {
int i = 0;
for (; (x > logs[i]) && (logs[i] != 0); ++i);
if (logs[i] == 0)
return 4096;
return logs[i];
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian::copy_texture
// Access: Public, Virtual
// Description: Copy the pixel region indicated by the display
// region from the framebuffer into texture memory
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian:: void DXGraphicsStateGuardian::
copy_texture(TextureContext *tc, const DisplayRegion *dr) { copy_texture(TextureContext *tc, const DisplayRegion *dr) {
nassertv(tc != NULL && dr != NULL); HRESULT hr;
int xo, yo, w, h;
dr->get_region_pixels(xo, yo, w, h);
Texture *tex = tc->_texture; DXTextureContext *dtc = DCAST(DXTextureContext, tc);
PixelBuffer *pb = dtc->_tex->_pbuffer;
pb->set_size(0,0,w-xo,h-yo);
// Determine the size of the grab from the given display region IDirect3DSurface8 *pTexSurfaceLev0,*pCurRenderTarget;
// If the requested region is not a power of two, grab a region that is hr = dtc->_pD3DTexture8->GetSurfaceLevel(0,&pTexSurfaceLev0);
// a power of two that contains the requested region if(FAILED(hr)) {
int xo, yo, req_w, req_h; dxgsg_cat.error() << "GetSurfaceLev failed in copy_texture" << D3DERRORSTRING(hr);
dr->get_region_pixels(xo, yo, req_w, req_h); exit(1);
int w = binary_log_cap(req_w); }
int h = binary_log_cap(req_h);
if (w != req_w || h != req_h) {
tex->_requested_w = req_w;
tex->_requested_h = req_h;
tex->_has_requested_size = true;
}
PixelBuffer *pb = tex->_pbuffer; hr = scrn.pD3DDevice->GetRenderTarget(&pCurRenderTarget);
if(FAILED(hr)) {
pb->set_xorg(xo); dxgsg_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr);
pb->set_yorg(yo); exit(1);
pb->set_xsize(w); }
pb->set_ysize(h);
bind_texture(tc); RECT SrcRect;
glCopyTexImage2D( GL_TEXTURE_2D, tex->get_level(),
get_internal_image_format(pb->get_format()), SrcRect.left = xo;
pb->get_xorg(), pb->get_yorg(), SrcRect.right = xo+w;
pb->get_xsize(), pb->get_ysize(), pb->get_border() ); SrcRect.top = yo;
SrcRect.bottom = yo+h;
// now copy from fb to tex
hr = scrn.pD3DDevice->CopyRects(pCurRenderTarget,&SrcRect,1,pTexSurfaceLev0,NULL);
if(FAILED(hr)) {
dxgsg_cat.error() << "CopyRects failed in copy_texture" << D3DERRORSTRING(hr);
exit(1);
}
SAFE_RELEASE(pCurRenderTarget);
SAFE_RELEASE(pTexSurfaceLev0);
} }
#endif
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian::copy_texture // Function: DXGraphicsStateGuardian::copy_texture

View File

@ -1530,248 +1530,6 @@ FillDDSurfTexturePixels(void) {
} }
RELEASE(pMipLevel0,dxgsg,"texture",RELEASE_ONCE); RELEASE(pMipLevel0,dxgsg,"texture",RELEASE_ONCE);
return hr; return hr;
/* old, custom conversion and mipmap-generation stuff
HRESULT hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,pbuf->_image.p(),_surface);
if(FAILED(hr)) {
return hr;
}
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
_surface->GetSurfaceDesc(&ddsd);
if(_bHasMipMaps) {
DWORD i,oldcurxsize,oldcurysize,curxsize,curysize,cMipMapCount=ddsd.dwMipMapCount;
assert(ddsd.dwMipMapCount<20);
DWORD cNumColorChannels = pbuf->get_num_components();
curxsize=ddsd.dwWidth; curysize=ddsd.dwHeight;
assert(pbuf->get_image_type()==PixelBuffer::T_unsigned_byte); // cant handle anything else now
// all mipmap sublevels require 1/3 of total original space. alloc 1/2 for safety
BYTE *pMipMapPixBufSpace = new BYTE[((curxsize*curysize*cNumColorChannels)/2)+1024];
LPDIRECTDRAWSURFACE7 pCurDDSurf=_surface;
pCurDDSurf->AddRef(); // so final release doesnt release the surface
BYTE *pDstWord = pMipMapPixBufSpace;
BYTE *pLastMipLevelStart = (BYTE *) pbuf->_image.p();
// clock_t start1,finish1;
// start1=clock();
for(i=1;i<ddsd.dwMipMapCount;i++) {
oldcurxsize=curxsize; oldcurysize=curysize;
curysize = max(curysize>>1,1);
curxsize = max(curxsize>>1,1);
assert(!((oldcurxsize==1)&&(oldcurysize==1)));
BYTE *pSrcWord;
BYTE *pSrcLineStart=pLastMipLevelStart;
// inc img start to DWORD boundary
while(((DWORD)pDstWord) & 0x11)
pDstWord++;
pLastMipLevelStart = pDstWord;
DWORD x,y,cPixelSize=cNumColorChannels;
DWORD src_row_bytelength=oldcurxsize*cPixelSize;
DWORD two_src_row_bytelength=2*src_row_bytelength;
#define GENMIPMAP_DO_INTEGER_DIV // should be a little faster, but no rounding up
#ifdef GENMIPMAP_DO_INTEGER_DIV
DWORD DivShift=2;
if((oldcurxsize==1)||(oldcurysize==1))
DivShift = 1;
#else
float numpixels_per_filter=4.0f;
if((oldcurxsize==1)||(oldcurysize==1))
numpixels_per_filter=2.0f;
#endif
DWORD x_srcptr_inc = ((oldcurxsize==1)? cPixelSize: (2*cPixelSize));
// box-filter shrink down, avg 4 pixels at a time
for(y=0; y<curysize; y++,pSrcLineStart+=two_src_row_bytelength) {
pSrcWord=pSrcLineStart;
for(x=0; x<curxsize; x++,pSrcWord+=x_srcptr_inc,pDstWord+=cPixelSize) {
// fetches, stores byte at a time.
// inefficient, but works for all channel sizes
for(int c=0;c<cPixelSize;c++) {
DWORD colr;
colr = *(pSrcWord+c);
if(oldcurxsize>1) // handle 1x[X], [X]x1 cases
colr += *(pSrcWord+cPixelSize+c);
if(oldcurysize>1) {
colr += *(pSrcWord+src_row_bytelength+c);
if(oldcurxsize>1)
colr += *(pSrcWord+src_row_bytelength+cPixelSize+c);
}
#ifdef GENMIPMAP_DO_INTEGER_DIV
colr >>= DivShift;
#else
colr = (DWORD) ((((float)colr)/numpixels_per_filter)+0.5f);
#endif
*(pDstWord+c)=(BYTE)colr;
}
}
}
// now copy pixbuf to final DD surf
DDSCAPS2 ddsCaps;
LPDIRECTDRAWSURFACE7 pMipLevel_DDSurf;
ZeroMemory(&ddsCaps,sizeof(DDSCAPS2));
ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
hr = pCurDDSurf->GetAttachedSurface(&ddsCaps, &pMipLevel_DDSurf);
if(FAILED(hr)) {
dxgsg_cat.error() << "CreateTexture failed creating mipmaps: GetAttachedSurf hr = " << D3DERRORSTRING(hr);
delete [] pMipMapPixBufSpace;
pCurDDSurf->Release();
return hr;
}
hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,pLastMipLevelStart,pMipLevel_DDSurf);
if(FAILED(hr)) {
delete [] pMipMapPixBufSpace;
pCurDDSurf->Release();
return hr;
}
pCurDDSurf->Release();
pCurDDSurf=pMipLevel_DDSurf;
}
// finish1=clock();
// double elapsed_time = (double)(finish1 - start1) / CLOCKS_PER_SEC;
// cerr << "mipmap gen takes " << elapsed_time << " secs for this texture\n";
delete [] pMipMapPixBufSpace;
pCurDDSurf->Release();
#ifdef _DEBUG
if(dx_debug_view_mipmaps) {
#if 0
if(!(ddcaps.dwCaps & DDCAPS_BLTSTRETCH)) {
dxgsg_cat.error() << "CreateTexture failed debug-viewing mipmaps, BLT stretching not supported! ( we need to do SW stretch) \n";
return hr;
}
#endif
// display mipmaps on primary surf
HDC hTexDC;
LPDIRECTDRAWSURFACE7 pTextureCurrent,pTexturePrev = _surface;
int cury,curx;
HDC hScreenDC;
RECT scrnrect;
hScreenDC=GetDC(NULL);
scrnrect.left=scrnrect.top=0;
scrnrect.bottom=GetDeviceCaps(hScreenDC,VERTRES);
scrnrect.right=GetDeviceCaps(hScreenDC,HORZRES);
char msg[500];
pTexturePrev->AddRef();
for(i = 0,curx=scrnrect.left,cury=scrnrect.top; i < ddsd.dwMipMapCount; i++) {
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_cur);
pTexturePrev->GetSurfaceDesc(&ddsd_cur);
hr = pTexturePrev->GetDC(&hTexDC);
if(FAILED(hr)) {
dxgsg_cat.error() << "GetDC failed hr = " << D3DERRORSTRING(hr);
break;
}
BOOL res;
// res = BitBlt(_dxgsg->_hdc,0,0,ddsd.dwWidth,ddsd.dwHeight, TexDC,0,0,SRCCOPY);
// loader inverts y, so use StretchBlt to re-invert it
// res = StretchBlt(_dxgsg->hdc,0,ddsd_cur.dwHeight+cury,ddsd_cur.dwWidth,-ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,SRCCOPY);
#if 0
if(cNumAlphaBits>0) {
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER; bf.BlendFlags=0;
bf.SourceConstantAlpha=255; bf.AlphaFormat=AC_SRC_ALPHA;
res = AlphaBlend(hScreenDC,curx,cury,ddsd_cur.dwWidth,ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,bf);
if(!res) {
PrintLastError(msg);
dxgsg_cat.error() << "AlphaBlend BLT failed: "<<msg<<"\n";
}
} else
#endif
{
res = StretchBlt(hScreenDC,curx,ddsd_cur.dwHeight+cury,ddsd_cur.dwWidth,-((int)ddsd_cur.dwHeight), hTexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,SRCCOPY);
if(!res) {
PrintLastError(msg);
dxgsg_cat.error() << "StretchBLT failed: "<<msg<<"\n";
}
}
// SetBkMode(hScreenDC, TRANSPARENT);
sprintf(msg,"%d",i);
TextOut(hScreenDC,curx+(ddsd_cur.dwWidth)/2,5+cury+ddsd_cur.dwHeight,msg,strlen(msg));
curx+=max(20,ddsd_cur.dwWidth+10);
if(curx>scrnrect.right) {
curx=0; cury+=(scrnrect.bottom-scrnrect.top)/2;
}
hr = pTexturePrev->ReleaseDC(hTexDC);
if(FAILED(hr)) {
dxgsg_cat.error() << "tex ReleaseDC failed for mip "<<i<<" hr = " << D3DERRORSTRING(hr);
break;
}
if(i==ddsd.dwMipMapCount-1) {
pTexturePrev->Release();
continue;
}
DDSCAPS2 ddsCaps;
ZeroMemory(&ddsCaps,sizeof(DDSCAPS2));
ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
hr = pTexturePrev->GetAttachedSurface(&ddsCaps, &pTextureCurrent);
if(FAILED(hr)) {
dxgsg_cat.error() << " failed displaying mipmaps: GetAttachedSurf hr = " << D3DERRORSTRING(hr);
}
// done with the previous texture
pTexturePrev->Release();
pTexturePrev = pTextureCurrent;
}
ReleaseDC(0,hScreenDC);
HANDLE hArr[1];
MSG winmsg;
hArr[0]=GetStdHandle(STD_INPUT_HANDLE);
GetMessage(&winmsg,NULL,0,0);
int val=MsgWaitForMultipleObjects(1,hArr,TRUE,INFINITE,QS_KEY);
if(val==-1) {
PrintLastError(msg);
dxgsg_cat.error() << " MsgWaitForMultipleObjects returns " << val << " " <<msg << endl;
} else {
dxgsg_cat.error() << " MsgWaitForMultipleObjects returns " << val << endl;
}
}
#endif
}
return S_OK;
*/
} }