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 @@
'libGLESv2/geometry/vertexconversion.h',
'libGLESv2/geometry/VertexDataManager.cpp',
'libGLESv2/geometry/VertexDataManager.h',
'libGLESv2/Blit.cpp',
'libGLESv2/Blit.h',
'libGLESv2/Buffer.cpp',
'libGLESv2/Buffer.h',
'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 @@
#include "geometry/VertexDataManager.h"
#include "geometry/IndexDataManager.h"
#include "geometry/dx9.h"
#include "Blit.h"
#undef near
#undef far
......@@ -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
// objects all of whose names are 0.
mTexture2DZero = new Texture2D();
mTextureCubeMapZero = new TextureCubeMap();
mTexture2DZero = new Texture2D(this);
mTextureCubeMapZero = new TextureCubeMap(this);
mColorbufferZero = NULL;
mDepthbufferZero = NULL;
......@@ -142,6 +143,7 @@ Context::Context(const egl::Config *config)
mBufferBackEnd = NULL;
mVertexDataManager = NULL;
mIndexDataManager = NULL;
mBlit = NULL;
mInvalidEnum = false;
mInvalidValue = false;
......@@ -171,6 +173,7 @@ Context::~Context()
delete mBufferBackEnd;
delete mVertexDataManager;
delete mIndexDataManager;
delete mBlit;
while (!mBufferMap.empty())
{
......@@ -212,6 +215,7 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
mBufferBackEnd = new Dx9BackEnd(device);
mVertexDataManager = new VertexDataManager(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
......@@ -501,7 +505,7 @@ void Context::bindTexture2D(GLuint texture)
{
if (!getTexture(texture) && texture != 0)
{
mTextureMap[texture] = new Texture2D();
mTextureMap[texture] = new Texture2D(this);
}
texture2D = texture;
......@@ -513,7 +517,7 @@ void Context::bindTextureCubeMap(GLuint texture)
{
if (!getTexture(texture) && texture != 0)
{
mTextureMap[texture] = new TextureCubeMap();
mTextureMap[texture] = new TextureCubeMap(this);
}
textureCubeMap = texture;
......@@ -2157,7 +2161,7 @@ Texture *Context::getIncompleteTexture(SamplerType type)
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);
t = incomplete2d;
}
......@@ -2165,7 +2169,7 @@ Texture *Context::getIncompleteTexture(SamplerType type)
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->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
......
......@@ -46,6 +46,7 @@ class Stencilbuffer;
class VertexDataManager;
class IndexDataManager;
class BufferBackEnd;
class Blit;
enum
{
......@@ -288,6 +289,8 @@ class Context : public State
const char *getPixelShaderProfile();
const char *getVertexShaderProfile();
Blit *getBlitter() { return mBlit; }
private:
DISALLOW_COPY_AND_ASSIGN(Context);
......@@ -334,6 +337,8 @@ class Context : public State
VertexDataManager *mVertexDataManager;
IndexDataManager *mIndexDataManager;
Blit *mBlit;
Texture *mIncompleteTextures[SAMPLER_TYPE_COUNT];
// Recorded errors
......
......@@ -21,6 +21,9 @@
namespace gl
{
class Context;
class Blit;
enum
{
MAX_TEXTURE_SIZE = 2048,
......@@ -32,7 +35,7 @@ enum
class Texture : public Colorbuffer
{
public:
Texture();
explicit Texture(Context *context);
~Texture();
......@@ -90,11 +93,17 @@ class Texture : public Colorbuffer
virtual bool dirtyImageData() const = 0;
void dropTexture();
void pushTexture(IDirect3DBaseTexture9 *newTexture);
Blit *getBlitter();
private:
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;
void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
......@@ -106,7 +115,7 @@ class Texture : public Colorbuffer
class Texture2D : public Texture
{
public:
Texture2D();
explicit Texture2D(Context *context);
~Texture2D();
......@@ -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 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;
......@@ -132,12 +143,14 @@ class Texture2D : public Texture
Image mImageArray[MAX_TEXTURE_LEVELS];
IDirect3DTexture9 *mTexture;
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height);
};
class TextureCubeMap : public Texture
{
public:
TextureCubeMap();
explicit TextureCubeMap(Context *context);
~TextureCubeMap();
......@@ -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 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;
......@@ -164,10 +179,15 @@ class TextureCubeMap : public Texture
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);
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);
bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width);
Image mImageArray[6][MAX_TEXTURE_LEVELS];
......
......@@ -791,12 +791,94 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
try
{
if (width < 0 || height < 0)
if (level < 0 || width < 0 || height < 0)
{
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&)
{
......@@ -812,13 +894,61 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
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);
}
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&)
{
return error(GL_OUT_OF_MEMORY);
......
......@@ -181,6 +181,10 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\Blit.cpp"
>
</File>
<File
RelativePath=".\Buffer.cpp"
>
</File>
......@@ -251,6 +255,10 @@
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\Blit.h"
>
</File>
<File
RelativePath=".\Buffer.h"
>
</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