Commit ae345807 by jbauman@chromium.org

Add support for eglBindTexImage and eglReleaseTexImage

With this patch we can bind pbuffers as textures. Once we add support for using a sharing handle to create a pbuffer we can use this to allow us to use it as a texture as well. BUG=129 TEST=modified Simple_Texture2D works Review URL: http://codereview.appspot.com/4291066/ git-svn-id: https://angleproject.googlecode.com/svn/trunk@604 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent b627699f
#define MAJOR_VERSION 0
#define MINOR_VERSION 0
#define BUILD_VERSION 0
#define BUILD_REVISION 598
#define BUILD_REVISION 604
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -64,6 +64,8 @@ void Config::setDefaults()
void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
{
mBindToTextureRGB = EGL_FALSE;
mBindToTextureRGBA = EGL_FALSE;
switch (renderTargetFormat)
{
case D3DFMT_A1R5G5B5:
......@@ -86,6 +88,7 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
mGreenSize = 8;
mBlueSize = 8;
mAlphaSize = 8;
mBindToTextureRGBA = true;
break;
case D3DFMT_R5G6B5:
mBufferSize = 16;
......@@ -100,6 +103,7 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
mGreenSize = 8;
mBlueSize = 8;
mAlphaSize = 0;
mBindToTextureRGB = true;
break;
default:
UNREACHABLE(); // Other formats should not be valid
......@@ -107,8 +111,6 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
mLuminanceSize = 0;
mAlphaMaskSize = 0;
mBindToTextureRGB = EGL_FALSE;
mBindToTextureRGBA = EGL_FALSE;
mColorBufferType = EGL_RGB_BUFFER;
mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
mConfigID = 0;
......
......@@ -412,11 +412,11 @@ Surface *Display::createWindowSurface(HWND window, EGLConfig config)
return surface;
}
Surface *Display::createOffscreenSurface(int width, int height, EGLConfig config)
Surface *Display::createOffscreenSurface(int width, int height, EGLConfig config, EGLenum textureFormat, EGLenum textureTarget)
{
const Config *configuration = mConfigSet.get(config);
Surface *surface = new Surface(this, configuration, width, height);
Surface *surface = new Surface(this, configuration, width, height, textureFormat, textureTarget);
mSurfaceSet.insert(surface);
return surface;
......@@ -637,6 +637,11 @@ bool Display::getLuminanceAlphaTextureSupport()
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
}
bool Display::getNonPow2TextureSupport()
{
return !(mDeviceCaps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL));
}
D3DPOOL Display::getBufferPool(DWORD usage) const
{
if (mD3d9Ex != NULL)
......
......@@ -43,7 +43,7 @@ class Display
bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
egl::Surface *createWindowSurface(HWND window, EGLConfig config);
egl::Surface *createOffscreenSurface(int width, int height, EGLConfig config);
egl::Surface *createOffscreenSurface(int width, int height, EGLConfig config, EGLenum textureFormat, EGLenum textureTarget);
EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
void destroySurface(egl::Surface *surface);
......@@ -68,6 +68,7 @@ class Display
virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
virtual bool getLuminanceTextureSupport();
virtual bool getLuminanceAlphaTextureSupport();
virtual bool getNonPow2TextureSupport();
virtual D3DPOOL getBufferPool(DWORD usage) const;
bool isD3d9ExDevice() { return mD3d9Ex != NULL; }
......
......@@ -13,6 +13,7 @@
#include "libEGL/Surface.h"
#include "common/debug.h"
#include "libGLESv2/Texture.h"
#include "libEGL/main.h"
#include "libEGL/Display.h"
......@@ -27,6 +28,9 @@ Surface::Surface(Display *display, const Config *config, HWND window)
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mShareHandle = NULL;
mTexture = NULL;
mTextureFormat = EGL_NO_TEXTURE;
mTextureTarget = EGL_NO_TEXTURE;
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER;
......@@ -38,7 +42,7 @@ Surface::Surface(Display *display, const Config *config, HWND window)
resetSwapChain();
}
Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height)
Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
: mDisplay(display), mWindow(NULL), mConfig(config), mWidth(width), mHeight(height)
{
mSwapChain = NULL;
......@@ -47,6 +51,9 @@ Surface::Surface(Display *display, const Config *config, EGLint width, EGLint he
mOffscreenTexture = NULL;
mShareHandle = NULL;
mWindowSubclassed = false;
mTexture = NULL;
mTextureFormat = textureFormat;
mTextureTarget = textureType;
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER;
......@@ -88,6 +95,12 @@ void Surface::release()
mOffscreenTexture->Release();
mOffscreenTexture = NULL;
}
if (mTexture)
{
mTexture->releaseTexImage();
mTexture = NULL;
}
}
void Surface::resetSwapChain()
......@@ -347,6 +360,16 @@ IDirect3DSurface9 *Surface::getDepthStencil()
return mDepthStencil;
}
IDirect3DTexture9 *Surface::getOffscreenTexture()
{
if (mOffscreenTexture)
{
mOffscreenTexture->AddRef();
}
return mOffscreenTexture;
}
void Surface::setSwapInterval(EGLint interval)
{
if (mSwapInterval == interval)
......@@ -361,4 +384,29 @@ void Surface::setSwapInterval(EGLint interval)
mPresentInterval = convertInterval(mSwapInterval);
mPresentIntervalDirty = true;
}
EGLenum Surface::getTextureFormat() const
{
return mTextureFormat;
}
EGLenum Surface::getTextureTarget() const
{
return mTextureTarget;
}
void Surface::setBoundTexture(gl::Texture2D *texture)
{
mTexture = texture;
}
gl::Texture2D *Surface::getBoundTexture() const
{
return mTexture;
}
D3DFORMAT Surface::getFormat() const
{
return mConfig->mRenderTargetFormat;
}
}
......@@ -17,6 +17,11 @@
#include "common/angleutils.h"
namespace gl
{
class Texture2D;
}
namespace egl
{
class Display;
......@@ -26,7 +31,7 @@ class Surface
{
public:
Surface(Display *display, const egl::Config *config, HWND window);
Surface(Display *display, const egl::Config *config, EGLint width, EGLint height);
Surface(Display *display, const egl::Config *config, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
~Surface();
......@@ -41,12 +46,20 @@ class Surface
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture();
HANDLE getShareHandle() { return mShareHandle; }
void setSwapInterval(EGLint interval);
bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
virtual EGLenum getTextureFormat() const;
virtual EGLenum getTextureTarget() const;
virtual D3DFORMAT getFormat() const;
virtual void setBoundTexture(gl::Texture2D *texture);
virtual gl::Texture2D *getBoundTexture() const;
private:
DISALLOW_COPY_AND_ASSIGN(Surface);
......@@ -77,13 +90,14 @@ private:
EGLint mPixelAspectRatio; // Display aspect ratio
EGLenum mRenderBuffer; // Render buffer
EGLenum mSwapBehavior; // Buffer swap behavior
// EGLenum textureFormat; // Format of texture: RGB, RGBA, or no texture
// EGLenum textureTarget; // Type of texture: 2D or no texture
EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture
EGLenum mTextureTarget; // Type of texture: 2D or no texture
// EGLenum vgAlphaFormat; // Alpha format for OpenVG
// EGLenum vgColorSpace; // Color space for OpenVG
EGLint mSwapInterval;
DWORD mPresentInterval;
bool mPresentIntervalDirty;
gl::Texture2D *mTexture;
};
}
......
......@@ -11,6 +11,8 @@
#include "common/debug.h"
#include "common/version.h"
#include "libGLESv2/Context.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/Texture.h"
#include "libEGL/main.h"
#include "libEGL/Display.h"
......@@ -392,6 +394,8 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
{
egl::Display *display = static_cast<egl::Display*>(dpy);
EGLint width = 0, height = 0;
EGLenum textureFormat = EGL_NO_TEXTURE;
EGLenum textureTarget = EGL_NO_TEXTURE;
if (!validate(display, config))
{
......@@ -415,10 +419,23 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
UNIMPLEMENTED(); // FIXME
break;
case EGL_TEXTURE_FORMAT:
switch (attrib_list[1])
{
case EGL_NO_TEXTURE:
case EGL_TEXTURE_RGB:
case EGL_TEXTURE_RGBA:
textureFormat = attrib_list[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
break;
case EGL_TEXTURE_TARGET:
switch (attrib_list[1])
{
case EGL_NO_TEXTURE:
case EGL_TEXTURE_2D:
textureTarget = attrib_list[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
......@@ -440,10 +457,47 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
}
}
if (width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
}
if (width == 0 || height == 0)
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
EGLSurface surface = (EGLSurface)display->createOffscreenSurface(width, height, config);
if (textureFormat != EGL_NO_TEXTURE && !display->getNonPow2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height)))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
(textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
EGLint surfaceTypeValue;
EGLint bindToTextureRGBValue;
EGLint bindToTextureRGBAValue;
display->getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceTypeValue);
display->getConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, &bindToTextureRGBValue);
display->getConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBAValue);
if (!(surfaceTypeValue & EGL_PBUFFER_BIT))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
if ((textureFormat == EGL_TEXTURE_RGB && bindToTextureRGBValue != EGL_TRUE) ||
(textureFormat == EGL_TEXTURE_RGBA && bindToTextureRGBAValue != EGL_TRUE))
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
EGLSurface surface = (EGLSurface)display->createOffscreenSurface(width, height, config, textureFormat, textureTarget);
return success(surface);
}
......@@ -779,15 +833,36 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *surf = static_cast<egl::Surface*>(surface);
if (!validate(display))
{
return EGL_FALSE;
}
// FIXME - need implementation
if (buffer != EGL_BACK_BUFFER)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
if (surface == EGL_NO_SURFACE || surf->getWindowHandle())
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
return success(EGL_FALSE);
if (surf->getBoundTexture())
{
return error(EGL_BAD_ACCESS, EGL_FALSE);
}
if (surf->getTextureFormat() == EGL_NO_TEXTURE)
{
return error(EGL_BAD_MATCH, EGL_FALSE);
}
glBindTexImage(surf);
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
{
......@@ -804,15 +879,36 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *surf = static_cast<egl::Surface*>(surface);
if (!validate(display))
{
return EGL_FALSE;
}
// FIXME - need implementation
if (buffer != EGL_BACK_BUFFER)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
if (surface == EGL_NO_SURFACE || surf->getWindowHandle())
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
if (surf->getTextureFormat() == EGL_NO_TEXTURE)
{
return error(EGL_BAD_MATCH, EGL_FALSE);
}
return success(EGL_FALSE);
gl::Texture2D *texture = surf->getBoundTexture();
if (texture)
{
texture->releaseTexImage();
}
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
{
......
......@@ -539,6 +539,7 @@ void glDestroyContext(gl::Context *context);
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
gl::Context *glGetCurrentContext();
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
void __stdcall glBindTexImage(egl::Surface *surface);
}
#endif // INCLUDE_CONTEXT_H_
......@@ -16,6 +16,8 @@
#include "common/debug.h"
#include "libEGL/Display.h"
#include "libGLESv2/main.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/utilities.h"
......@@ -1209,6 +1211,7 @@ unsigned int Texture::issueSerial()
Texture2D::Texture2D(GLuint id) : Texture(id)
{
mTexture = NULL;
mSurface = NULL;
}
Texture2D::~Texture2D()
......@@ -1220,6 +1223,12 @@ Texture2D::~Texture2D()
mTexture->Release();
mTexture = NULL;
}
if (mSurface)
{
mSurface->setBoundTexture(NULL);
mSurface = NULL;
}
}
GLenum Texture2D::getTarget() const
......@@ -1252,7 +1261,7 @@ D3DFORMAT Texture2D::getD3DFormat() const
return mImageArray[0].getD3DFormat();
}
void Texture2D::redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
void Texture2D::redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRedefine)
{
GLsizei textureWidth = mImageArray[0].width;
GLsizei textureHeight = mImageArray[0].height;
......@@ -1273,7 +1282,7 @@ void Texture2D::redefineTexture(GLint level, GLenum format, GLsizei width, GLsiz
bool heightOkay = (textureHeight >> level == height) || (textureHeight >> level == 0 && height == 1);
bool textureOkay = (widthOkay && heightOkay && textureFormat == format && textureType == type);
if (!textureOkay) // Purge all the levels and the texture.
if (!textureOkay || forceRedefine || mSurface) // Purge all the levels and the texture.
{
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
......@@ -1292,19 +1301,58 @@ void Texture2D::redefineTexture(GLint level, GLenum format, GLsizei width, GLsiz
mDirtyImage = true;
mIsRenderable = false;
}
if (mSurface)
{
mSurface->setBoundTexture(NULL);
mSurface = NULL;
}
}
}
void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
redefineTexture(level, format, width, height, type);
redefineTexture(level, format, width, height, type, false);
Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
}
void Texture2D::bindTexImage(egl::Surface *surface)
{
GLenum format;
switch(surface->getFormat())
{
case D3DFMT_A8R8G8B8:
format = GL_RGBA;
break;
case D3DFMT_X8R8G8B8:
format = GL_RGB;
break;
default:
UNIMPLEMENTED();
return;
}
redefineTexture(0, format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
IDirect3DTexture9 *texture = surface->getOffscreenTexture();
mTexture = texture;
mDirtyImage = true;
mIsRenderable = true;
mSurface = surface;
mSurface->setBoundTexture(this);
}
void Texture2D::releaseTexImage()
{
redefineTexture(0, GL_RGB, 0, 0, GL_UNSIGNED_BYTE, true);
}
void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE);
redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE, false);
Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
}
......@@ -1366,7 +1414,7 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei
return error(GL_OUT_OF_MEMORY);
}
redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE);
redefineTexture(level, format, width, height, GL_UNSIGNED_BYTE, false);
if (!mImageArray[level].isRenderable())
{
......@@ -1413,7 +1461,7 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_OUT_OF_MEMORY);
}
redefineTexture(level, mImageArray[level].format, mImageArray[level].width, mImageArray[level].height, GL_UNSIGNED_BYTE);
redefineTexture(level, mImageArray[level].format, mImageArray[level].width, mImageArray[level].height, GL_UNSIGNED_BYTE, false);
if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete()))
{
......
......@@ -22,6 +22,11 @@
#include "libGLESv2/utilities.h"
#include "common/debug.h"
namespace egl
{
class Surface;
}
namespace gl
{
class Blit;
......@@ -210,6 +215,8 @@ class Texture2D : public Texture
virtual bool isComplete() const;
virtual bool isCompressed() const;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
virtual void generateMipmaps();
......@@ -224,12 +231,13 @@ class Texture2D : public Texture
virtual void convertToRenderTarget();
virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
void redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
void redefineTexture(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool force);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
IDirect3DTexture9 *mTexture;
egl::Surface *mSurface;
BindingPointer<Renderbuffer> mColorbufferProxy;
};
......
......@@ -5701,4 +5701,29 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *
return NULL;
}
void __stdcall glBindTexImage(egl::Surface *surface)
{
EVENT("(egl::Surface* surface = 0x%0.8p)",
surface);
try
{
gl::Context *context = gl::getContext();
if (context)
{
gl::Texture2D *textureObject = context->getTexture2D();
if (textureObject)
{
textureObject->bindTexImage(surface);
}
}
}
catch(std::bad_alloc&)
{
return error(GL_OUT_OF_MEMORY);
}
}
}
......@@ -160,4 +160,5 @@ EXPORTS
glDestroyContext @145 NONAME
glMakeCurrent @146 NONAME
glGetCurrentContext @147 NONAME
glGetProcAddress @148 NONAME
\ No newline at end of file
glGetProcAddress @148 NONAME
glBindTexImage @158 NONAME
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