Implement CopyTex(Sub)Image2D

TRAC #11474 Signed-off-by: Shannon Woods Signed-off-by: Daniel Koch Author: Andrew Lewycky git-svn-id: https://angleproject.googlecode.com/svn/trunk@132 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 98079839
...@@ -158,6 +158,8 @@ ...@@ -158,6 +158,8 @@
'libGLESv2/geometry/vertexconversion.h', 'libGLESv2/geometry/vertexconversion.h',
'libGLESv2/geometry/VertexDataManager.cpp', 'libGLESv2/geometry/VertexDataManager.cpp',
'libGLESv2/geometry/VertexDataManager.h', 'libGLESv2/geometry/VertexDataManager.h',
'libGLESv2/Blit.cpp',
'libGLESv2/Blit.h',
'libGLESv2/Buffer.cpp', 'libGLESv2/Buffer.cpp',
'libGLESv2/Buffer.h', 'libGLESv2/Buffer.h',
'libGLESv2/Context.cpp', 'libGLESv2/Context.cpp',
......
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Blit.cpp: Surface copy utility class.
#ifndef LIBGLESV2_BLIT_H_
#define LIBGLESV2_BLIT_H_
#include <map>
#define GL_APICALL
#include <GLES2/gl2.h>
#include <d3d9.h>
#include "common/angleutils.h"
namespace gl
{
class Context;
class Blit
{
public:
explicit Blit(Context *context);
~Blit();
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in OpenGL coordinates. Assumes that source is internally flipped (for example as a render target would be).
// source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
private:
Context *mContext;
IDirect3DVertexBuffer9 *mQuadVertexBuffer;
IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
void initGeometry();
bool setFormatConvertShaders(GLenum destFormat);
IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect);
void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
void setCommonBlitState();
// This enum is used to index mCompiledShaders and mShaderSource.
enum ShaderId
{
SHADER_VS_STANDARD,
SHADER_VS_FLIPY,
SHADER_PS_PASSTHROUGH,
SHADER_PS_LUMINANCE,
SHADER_PS_COMPONENTMASK,
SHADER_COUNT
};
static const char * const mShaderSource[];
// This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
IUnknown *mCompiledShaders[SHADER_COUNT];
template <class D3DShaderType>
bool setShader(ShaderId source, const char *profile,
HRESULT (WINAPI IDirect3DDevice9::*createShader)(const DWORD *, D3DShaderType **),
HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
bool setVertexShader(ShaderId shader);
bool setPixelShader(ShaderId shader);
void render();
DISALLOW_COPY_AND_ASSIGN(Blit);
};
}
#endif // LIBGLESV2_BLIT_H_
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "geometry/VertexDataManager.h" #include "geometry/VertexDataManager.h"
#include "geometry/IndexDataManager.h" #include "geometry/IndexDataManager.h"
#include "geometry/dx9.h" #include "geometry/dx9.h"
#include "Blit.h"
#undef near #undef near
#undef far #undef far
...@@ -106,8 +107,8 @@ Context::Context(const egl::Config *config) ...@@ -106,8 +107,8 @@ Context::Context(const egl::Config *config)
// In order that access to these initial textures not be lost, they are treated as texture // In order that access to these initial textures not be lost, they are treated as texture
// objects all of whose names are 0. // objects all of whose names are 0.
mTexture2DZero = new Texture2D(); mTexture2DZero = new Texture2D(this);
mTextureCubeMapZero = new TextureCubeMap(); mTextureCubeMapZero = new TextureCubeMap(this);
mColorbufferZero = NULL; mColorbufferZero = NULL;
mDepthbufferZero = NULL; mDepthbufferZero = NULL;
...@@ -142,6 +143,7 @@ Context::Context(const egl::Config *config) ...@@ -142,6 +143,7 @@ Context::Context(const egl::Config *config)
mBufferBackEnd = NULL; mBufferBackEnd = NULL;
mVertexDataManager = NULL; mVertexDataManager = NULL;
mIndexDataManager = NULL; mIndexDataManager = NULL;
mBlit = NULL;
mInvalidEnum = false; mInvalidEnum = false;
mInvalidValue = false; mInvalidValue = false;
...@@ -171,6 +173,7 @@ Context::~Context() ...@@ -171,6 +173,7 @@ Context::~Context()
delete mBufferBackEnd; delete mBufferBackEnd;
delete mVertexDataManager; delete mVertexDataManager;
delete mIndexDataManager; delete mIndexDataManager;
delete mBlit;
while (!mBufferMap.empty()) while (!mBufferMap.empty())
{ {
...@@ -212,6 +215,7 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) ...@@ -212,6 +215,7 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
mBufferBackEnd = new Dx9BackEnd(device); mBufferBackEnd = new Dx9BackEnd(device);
mVertexDataManager = new VertexDataManager(this, mBufferBackEnd); mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
mIndexDataManager = new IndexDataManager(this, mBufferBackEnd); mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
mBlit = new Blit(this);
} }
// Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
...@@ -501,7 +505,7 @@ void Context::bindTexture2D(GLuint texture) ...@@ -501,7 +505,7 @@ void Context::bindTexture2D(GLuint texture)
{ {
if (!getTexture(texture) && texture != 0) if (!getTexture(texture) && texture != 0)
{ {
mTextureMap[texture] = new Texture2D(); mTextureMap[texture] = new Texture2D(this);
} }
texture2D = texture; texture2D = texture;
...@@ -513,7 +517,7 @@ void Context::bindTextureCubeMap(GLuint texture) ...@@ -513,7 +517,7 @@ void Context::bindTextureCubeMap(GLuint texture)
{ {
if (!getTexture(texture) && texture != 0) if (!getTexture(texture) && texture != 0)
{ {
mTextureMap[texture] = new TextureCubeMap(); mTextureMap[texture] = new TextureCubeMap(this);
} }
textureCubeMap = texture; textureCubeMap = texture;
...@@ -2157,7 +2161,7 @@ Texture *Context::getIncompleteTexture(SamplerType type) ...@@ -2157,7 +2161,7 @@ Texture *Context::getIncompleteTexture(SamplerType type)
case SAMPLER_2D: case SAMPLER_2D:
{ {
Texture2D *incomplete2d = new Texture2D; Texture2D *incomplete2d = new Texture2D(this);
incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
t = incomplete2d; t = incomplete2d;
} }
...@@ -2165,7 +2169,7 @@ Texture *Context::getIncompleteTexture(SamplerType type) ...@@ -2165,7 +2169,7 @@ Texture *Context::getIncompleteTexture(SamplerType type)
case SAMPLER_CUBE: case SAMPLER_CUBE:
{ {
TextureCubeMap *incompleteCube = new TextureCubeMap; TextureCubeMap *incompleteCube = new TextureCubeMap(this);
incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
......
...@@ -46,6 +46,7 @@ class Stencilbuffer; ...@@ -46,6 +46,7 @@ class Stencilbuffer;
class VertexDataManager; class VertexDataManager;
class IndexDataManager; class IndexDataManager;
class BufferBackEnd; class BufferBackEnd;
class Blit;
enum enum
{ {
...@@ -288,6 +289,8 @@ class Context : public State ...@@ -288,6 +289,8 @@ class Context : public State
const char *getPixelShaderProfile(); const char *getPixelShaderProfile();
const char *getVertexShaderProfile(); const char *getVertexShaderProfile();
Blit *getBlitter() { return mBlit; }
private: private:
DISALLOW_COPY_AND_ASSIGN(Context); DISALLOW_COPY_AND_ASSIGN(Context);
...@@ -334,6 +337,8 @@ class Context : public State ...@@ -334,6 +337,8 @@ class Context : public State
VertexDataManager *mVertexDataManager; VertexDataManager *mVertexDataManager;
IndexDataManager *mIndexDataManager; IndexDataManager *mIndexDataManager;
Blit *mBlit;
Texture *mIncompleteTextures[SAMPLER_TYPE_COUNT]; Texture *mIncompleteTextures[SAMPLER_TYPE_COUNT];
// Recorded errors // Recorded errors
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
namespace gl namespace gl
{ {
class Context;
class Blit;
enum enum
{ {
MAX_TEXTURE_SIZE = 2048, MAX_TEXTURE_SIZE = 2048,
...@@ -32,7 +35,7 @@ enum ...@@ -32,7 +35,7 @@ enum
class Texture : public Colorbuffer class Texture : public Colorbuffer
{ {
public: public:
Texture(); explicit Texture(Context *context);
~Texture(); ~Texture();
...@@ -90,11 +93,17 @@ class Texture : public Colorbuffer ...@@ -90,11 +93,17 @@ class Texture : public Colorbuffer
virtual bool dirtyImageData() const = 0; virtual bool dirtyImageData() const = 0;
void dropTexture();
void pushTexture(IDirect3DBaseTexture9 *newTexture);
Blit *getBlitter();
private: private:
DISALLOW_COPY_AND_ASSIGN(Texture); DISALLOW_COPY_AND_ASSIGN(Texture);
IDirect3DBaseTexture9 *mBaseTexture; // This is a weak pointer. The derived class is assumed to own a strong pointer. Context *mContext;
IDirect3DBaseTexture9 *mBaseTexture; // This is a weak pointer. The derived class is assumed to own a strong pointer.
bool mDirtyMetaData; bool mDirtyMetaData;
void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
...@@ -106,7 +115,7 @@ class Texture : public Colorbuffer ...@@ -106,7 +115,7 @@ class Texture : public Colorbuffer
class Texture2D : public Texture class Texture2D : public Texture
{ {
public: public:
Texture2D(); explicit Texture2D(Context *context);
~Texture2D(); ~Texture2D();
...@@ -114,6 +123,8 @@ class Texture2D : public Texture ...@@ -114,6 +123,8 @@ class Texture2D : public Texture
void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source);
void copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source);
bool isComplete() const; bool isComplete() const;
...@@ -132,12 +143,14 @@ class Texture2D : public Texture ...@@ -132,12 +143,14 @@ class Texture2D : public Texture
Image mImageArray[MAX_TEXTURE_LEVELS]; Image mImageArray[MAX_TEXTURE_LEVELS];
IDirect3DTexture9 *mTexture; IDirect3DTexture9 *mTexture;
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height);
}; };
class TextureCubeMap : public Texture class TextureCubeMap : public Texture
{ {
public: public:
TextureCubeMap(); explicit TextureCubeMap(Context *context);
~TextureCubeMap(); ~TextureCubeMap();
...@@ -151,6 +164,8 @@ class TextureCubeMap : public Texture ...@@ -151,6 +164,8 @@ class TextureCubeMap : public Texture
void setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); void setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); void subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source);
void copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Renderbuffer *source);
bool isComplete() const; bool isComplete() const;
...@@ -164,10 +179,15 @@ class TextureCubeMap : public Texture ...@@ -164,10 +179,15 @@ class TextureCubeMap : public Texture
virtual bool dirtyImageData() const; virtual bool dirtyImageData() const;
// faceIdentifier is 0-5 or one of the GL_TEXTURE_CUBE_MAP_* enumerants.
// Returns NULL if the call underlying Direct3D call fails.
IDirect3DSurface9 *getCubeMapSurface(unsigned int faceIdentifier, unsigned int level);
static unsigned int faceIndex(GLenum face); static unsigned int faceIndex(GLenum face);
void setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); void setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width);
Image mImageArray[6][MAX_TEXTURE_LEVELS]; Image mImageArray[6][MAX_TEXTURE_LEVELS];
......
...@@ -791,12 +791,94 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma ...@@ -791,12 +791,94 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
try try
{ {
if (width < 0 || height < 0) if (level < 0 || width < 0 || height < 0)
{ {
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
UNIMPLEMENTED(); // FIXME if (level > 0 && (!gl::isPow2(width) || !gl::isPow2(height)))
{
return error(GL_INVALID_VALUE);
}
switch (target)
{
case GL_TEXTURE_2D:
if (width > (gl::MAX_TEXTURE_SIZE >> level) || height > (gl::MAX_TEXTURE_SIZE >> level))
{
return error(GL_INVALID_VALUE);
}
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (!gl::isPow2(width) || !gl::isPow2(height))
{
return error(GL_INVALID_VALUE);
}
if (width > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level) || height > (gl::MAX_CUBE_MAP_TEXTURE_SIZE >> level))
{
return error(GL_INVALID_VALUE);
}
break;
default:
return error(GL_INVALID_ENUM);
}
switch (internalformat)
{
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RGB:
case GL_RGBA:
break;
default:
return error(GL_INVALID_VALUE);
}
if (border != 0)
{
return error(GL_INVALID_VALUE);
}
gl::Context *context = gl::getContext();
if (context)
{
gl::Renderbuffer *source = context->getFramebuffer()->getColorbuffer();
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
if (!texture)
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(level, internalformat, x, y, width, height, source);
}
else if (es2dx::IsCubemapTextureTarget(target))
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
if (!texture)
{
return error(GL_INVALID_OPERATION);
}
texture->copyImage(target, level, internalformat, x, y, width, height, source);
}
else
{
UNREACHABLE();
}
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
...@@ -812,13 +894,61 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL ...@@ -812,13 +894,61 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
try try
{ {
if (width < 0 || height < 0) if (target != GL_TEXTURE_2D && !es2dx::IsCubemapTextureTarget(target))
{
return error(GL_INVALID_ENUM);
}
if (level < 0 || level > gl::MAX_TEXTURE_LEVELS || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
{ {
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
UNIMPLEMENTED(); // FIXME if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
{
return error(GL_INVALID_VALUE);
}
if (width == 0 || height == 0)
{
return;
}
gl::Context *context = gl::getContext();
if (context)
{
gl::Renderbuffer *source = context->getFramebuffer()->getColorbuffer();
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
if (!texture)
{
return error(GL_INVALID_OPERATION);
}
texture->copySubImage(level, xoffset, yoffset, x, y, width, height, source);
}
else if (es2dx::IsCubemapTextureTarget(target))
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
if (!texture)
{
return error(GL_INVALID_OPERATION);
}
texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source);
}
else
{
UNREACHABLE();
}
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
return error(GL_OUT_OF_MEMORY); return error(GL_OUT_OF_MEMORY);
......
...@@ -181,6 +181,10 @@ ...@@ -181,6 +181,10 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
> >
<File <File
RelativePath=".\Blit.cpp"
>
</File>
<File
RelativePath=".\Buffer.cpp" RelativePath=".\Buffer.cpp"
> >
</File> </File>
...@@ -251,6 +255,10 @@ ...@@ -251,6 +255,10 @@
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
> >
<File <File
RelativePath=".\Blit.h"
>
</File>
<File
RelativePath=".\Buffer.h" RelativePath=".\Buffer.h"
> >
</File> </File>
......
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