Use D3DX to copy between renderable texture surfaces.

TRAC #16118 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@598 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 549bdefe
#define MAJOR_VERSION 0 #define MAJOR_VERSION 0
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 594 #define BUILD_REVISION 598
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -957,174 +957,187 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL ...@@ -957,174 +957,187 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL
return true; return true;
} }
// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
void Texture::copyNonRenderable(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget) void Texture::copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
{ {
if (!image->surface)
{
createSurface(image);
if (!image->surface)
{
ERR("Failed to create an image surface.");
return error(GL_OUT_OF_MEMORY);
}
}
IDirect3DDevice9 *device = getDevice(); IDirect3DDevice9 *device = getDevice();
IDirect3DSurface9 *surface = NULL; IDirect3DSurface9 *renderTargetData = NULL;
D3DSURFACE_DESC description; D3DSURFACE_DESC description;
renderTarget->GetDesc(&description); renderTarget->GetDesc(&description);
HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &surface, NULL); HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
if (!SUCCEEDED(result)) if (FAILED(result))
{ {
ERR("Could not create matching destination surface."); ERR("Could not create matching destination surface.");
return error(GL_OUT_OF_MEMORY); return error(GL_OUT_OF_MEMORY);
} }
result = device->GetRenderTargetData(renderTarget, surface); result = device->GetRenderTargetData(renderTarget, renderTargetData);
if (!SUCCEEDED(result)) if (FAILED(result))
{ {
ERR("GetRenderTargetData unexpectedly failed."); ERR("GetRenderTargetData unexpectedly failed.");
surface->Release(); renderTargetData->Release();
return error(GL_OUT_OF_MEMORY); return error(GL_OUT_OF_MEMORY);
} }
D3DLOCKED_RECT sourceLock = {0};
RECT sourceRect = transformPixelRect(x, y, width, height, description.Height); RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
result = surface->LockRect(&sourceLock, &sourceRect, 0); int destYOffset = transformPixelYOffset(yoffset, height, image->height);
RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
if (FAILED(result))
{
ERR("Failed to lock the source surface (rectangle might be invalid).");
surface->UnlockRect();
surface->Release();
return error(GL_OUT_OF_MEMORY);
}
if (!image->surface) if (image->isRenderable())
{ {
createSurface(image); result = D3DXLoadSurfaceFromSurface(image->surface, NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
if (FAILED(result))
{
ERR("Copying surfaces unexpectedly failed.");
renderTargetData->Release();
return error(GL_OUT_OF_MEMORY);
}
} }
else
if (image->surface == NULL)
{ {
ERR("Failed to create an image surface."); D3DLOCKED_RECT sourceLock = {0};
surface->UnlockRect(); result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
surface->Release();
return error(GL_OUT_OF_MEMORY);
}
D3DLOCKED_RECT destLock = {0}; if (FAILED(result))
int destYOffset = transformPixelYOffset(yoffset, height, image->height); {
RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height}; ERR("Failed to lock the source surface (rectangle might be invalid).");
result = image->surface->LockRect(&destLock, &destRect, 0); renderTargetData->Release();
return error(GL_OUT_OF_MEMORY);
if (FAILED(result)) }
{
ERR("Failed to lock the destination surface (rectangle might be invalid).");
surface->UnlockRect();
surface->Release();
return error(GL_OUT_OF_MEMORY);
}
if (destLock.pBits && sourceLock.pBits) D3DLOCKED_RECT destLock = {0};
{ result = image->surface->LockRect(&destLock, &destRect, 0);
unsigned char *source = (unsigned char*)sourceLock.pBits;
unsigned char *dest = (unsigned char*)destLock.pBits; if (FAILED(result))
{
ERR("Failed to lock the destination surface (rectangle might be invalid).");
renderTargetData->UnlockRect();
renderTargetData->Release();
return error(GL_OUT_OF_MEMORY);
}
switch (description.Format) if (destLock.pBits && sourceLock.pBits)
{ {
case D3DFMT_X8R8G8B8: unsigned char *source = (unsigned char*)sourceLock.pBits;
case D3DFMT_A8R8G8B8: unsigned char *dest = (unsigned char*)destLock.pBits;
switch(image->getD3DFormat())
switch (description.Format)
{ {
case D3DFMT_L8: case D3DFMT_X8R8G8B8:
for(int y = 0; y < height; y++) case D3DFMT_A8R8G8B8:
switch(image->getD3DFormat())
{ {
for(int x = 0; x < width; x++) case D3DFMT_L8:
for(int y = 0; y < height; y++)
{ {
dest[x] = source[x * 4 + 2]; for(int x = 0; x < width; x++)
} {
dest[x] = source[x * 4 + 2];
}
source += sourceLock.Pitch; source += sourceLock.Pitch;
dest += destLock.Pitch; dest += destLock.Pitch;
} }
break; break;
case D3DFMT_A8L8: case D3DFMT_A8L8:
for(int y = 0; y < height; y++) for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{ {
dest[x * 2 + 0] = source[x * 4 + 2]; for(int x = 0; x < width; x++)
dest[x * 2 + 1] = source[x * 4 + 3]; {
dest[x * 2 + 0] = source[x * 4 + 2];
dest[x * 2 + 1] = source[x * 4 + 3];
}
source += sourceLock.Pitch;
dest += destLock.Pitch;
} }
break;
source += sourceLock.Pitch; default:
dest += destLock.Pitch; UNREACHABLE();
} }
break; break;
default: case D3DFMT_R5G6B5:
UNREACHABLE(); switch(image->getD3DFormat())
}
break;
case D3DFMT_R5G6B5:
switch(image->getD3DFormat())
{
case D3DFMT_L8:
for(int y = 0; y < height; y++)
{ {
for(int x = 0; x < width; x++) case D3DFMT_L8:
for(int y = 0; y < height; y++)
{ {
unsigned char red = source[x * 2 + 1] & 0xF8; for(int x = 0; x < width; x++)
dest[x] = red | (red >> 5); {
unsigned char red = source[x * 2 + 1] & 0xF8;
dest[x] = red | (red >> 5);
}
source += sourceLock.Pitch;
dest += destLock.Pitch;
} }
break;
source += sourceLock.Pitch; default:
dest += destLock.Pitch; UNREACHABLE();
} }
break; break;
default: case D3DFMT_A1R5G5B5:
UNREACHABLE(); switch(image->getD3DFormat())
}
break;
case D3DFMT_A1R5G5B5:
switch(image->getD3DFormat())
{
case D3DFMT_L8:
for(int y = 0; y < height; y++)
{ {
for(int x = 0; x < width; x++) case D3DFMT_L8:
for(int y = 0; y < height; y++)
{ {
unsigned char red = source[x * 2 + 1] & 0x7C; for(int x = 0; x < width; x++)
dest[x] = (red << 1) | (red >> 4); {
unsigned char red = source[x * 2 + 1] & 0x7C;
dest[x] = (red << 1) | (red >> 4);
}
source += sourceLock.Pitch;
dest += destLock.Pitch;
} }
break;
source += sourceLock.Pitch; case D3DFMT_A8L8:
dest += destLock.Pitch; for(int y = 0; y < height; y++)
}
break;
case D3DFMT_A8L8:
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{ {
unsigned char red = source[x * 2 + 1] & 0x7C; for(int x = 0; x < width; x++)
dest[x * 2 + 0] = (red << 1) | (red >> 4); {
dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; unsigned char red = source[x * 2 + 1] & 0x7C;
dest[x * 2 + 0] = (red << 1) | (red >> 4);
dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
}
source += sourceLock.Pitch;
dest += destLock.Pitch;
} }
break;
source += sourceLock.Pitch; default:
dest += destLock.Pitch; UNREACHABLE();
} }
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
break;
default:
UNREACHABLE();
} }
image->dirty = true; image->surface->UnlockRect();
mDirtyImage = true; renderTargetData->UnlockRect();
} }
image->surface->UnlockRect(); renderTargetData->Release();
surface->UnlockRect();
surface->Release(); image->dirty = true;
mDirtyImage = true;
} }
IDirect3DBaseTexture9 *Texture::getTexture() IDirect3DBaseTexture9 *Texture::getTexture()
...@@ -1357,7 +1370,7 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei ...@@ -1357,7 +1370,7 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei
if (!mImageArray[level].isRenderable()) if (!mImageArray[level].isRenderable())
{ {
copyNonRenderable(&mImageArray[level], 0, 0, x, y, width, height, renderTarget); copyToImage(&mImageArray[level], 0, 0, x, y, width, height, renderTarget);
} }
else else
{ {
...@@ -1404,7 +1417,7 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -1404,7 +1417,7 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete())) if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete()))
{ {
copyNonRenderable(&mImageArray[level], xoffset, yoffset, x, y, width, height, renderTarget); copyToImage(&mImageArray[level], xoffset, yoffset, x, y, width, height, renderTarget);
} }
else else
{ {
...@@ -2199,7 +2212,7 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint ...@@ -2199,7 +2212,7 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint
if (!mImageArray[faceindex][level].isRenderable()) if (!mImageArray[faceindex][level].isRenderable())
{ {
copyNonRenderable(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget); copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
} }
else else
{ {
...@@ -2265,7 +2278,7 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi ...@@ -2265,7 +2278,7 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi
if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isComplete())) if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isComplete()))
{ {
copyNonRenderable(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget); copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
} }
else else
{ {
......
...@@ -105,7 +105,7 @@ class Texture : public RefCountObject ...@@ -105,7 +105,7 @@ class Texture : public RefCountObject
bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image); bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);
void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image); bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image);
void copyNonRenderable(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget); void copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const; GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const;
GLint creationLevels(GLsizei size, GLint maxlevel) const; GLint creationLevels(GLsizei size, GLint maxlevel) const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment