Commit 7b1f3abe by Nicolas Capens

Implement basic GL_OES_draw_texture functionality.

Change-Id: If242cfd4df1a7519152946b3d2364fc180f8ffae Reviewed-on: https://swiftshader-review.googlesource.com/2720Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarGreg Hartman <ghartman@google.com> Tested-by: 's avatarGreg Hartman <ghartman@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent ef1ac39e
...@@ -2121,7 +2121,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, ...@@ -2121,7 +2121,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
switch(type) switch(type)
{ {
case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5:
dest16[i] = dest16[i] =
((unsigned short)(31 * b + 0.5f) << 0) | ((unsigned short)(31 * b + 0.5f) << 0) |
((unsigned short)(63 * g + 0.5f) << 5) | ((unsigned short)(63 * g + 0.5f) << 5) |
((unsigned short)(31 * r + 0.5f) << 11); ((unsigned short)(31 * r + 0.5f) << 11);
...@@ -2274,6 +2274,56 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void * ...@@ -2274,6 +2274,56 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
} }
} }
void Context::drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
{
es1::Framebuffer *framebuffer = getFramebuffer();
es1::Renderbuffer *renderbuffer = framebuffer->getColorbuffer();
float targetWidth = renderbuffer->getWidth();
float targetHeight = renderbuffer->getHeight();
float x0 = 2.0f * x / targetWidth - 1.0f;
float y0 = 2.0f * y / targetHeight - 1.0f;
float x1 = 2.0f * (x + width) / targetWidth - 1.0f;
float y1 = 2.0f * (y + height) / targetHeight - 1.0f;
float Zw = sw::clamp(mState.zNear + z * (mState.zFar - mState.zNear), mState.zNear, mState.zFar);
float vertices[][3] = {{x0, y0, Zw},
{x0, y1, Zw},
{x1, y0, Zw},
{x1, y1, Zw}};
ASSERT(mState.samplerTexture[TEXTURE_2D][1].name() == 0); // Multi-texturing unimplemented
es1::Texture *texture = getSamplerTexture(0, TEXTURE_2D);
float textureWidth = texture->getWidth(GL_TEXTURE_2D, 0);
float textureHeight = texture->getHeight(GL_TEXTURE_2D, 0);
int Ucr = texture->getCropRectU();
int Vcr = texture->getCropRectV();
int Wcr = texture->getCropRectW();
int Hcr = texture->getCropRectH();
float texCoords[][2] = {{Ucr / textureWidth, Vcr / textureHeight},
{Ucr / textureWidth, (Vcr + Hcr) / textureHeight},
{(Ucr + Wcr) / textureWidth, Vcr / textureHeight},
{(Ucr + Wcr) / textureWidth, (Vcr + Hcr) / textureHeight}};
VertexAttribute oldPositionAttribute = mState.vertexAttribute[sw::Position];
VertexAttribute oldTexCoord0Attribute = mState.vertexAttribute[sw::TexCoord0];
glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(float), texCoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
textureStack0.push();
textureStack0.identity(); // Disable texture coordinate transformation
drawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Restore state
mState.vertexAttribute[sw::Position] = oldPositionAttribute;
mState.vertexAttribute[sw::TexCoord0] = oldTexCoord0Attribute;
textureStack0.pop();
}
void Context::finish() void Context::finish()
{ {
device->finish(); device->finish();
......
...@@ -282,7 +282,7 @@ public: ...@@ -282,7 +282,7 @@ public:
bool isDepthTestEnabled() const; bool isDepthTestEnabled() const;
void setDepthFunc(GLenum depthFunc); void setDepthFunc(GLenum depthFunc);
void setDepthRange(float zNear, float zFar); void setDepthRange(float zNear, float zFar);
void setBlend(bool enabled); void setBlend(bool enabled);
bool isBlendEnabled() const; bool isBlendEnabled() const;
void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
...@@ -293,7 +293,7 @@ public: ...@@ -293,7 +293,7 @@ public:
void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
void setStencilWritemask(GLuint stencilWritemask); void setStencilWritemask(GLuint stencilWritemask);
void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
void setPolygonOffsetFill(bool enabled); void setPolygonOffsetFill(bool enabled);
bool isPolygonOffsetFillEnabled() const; bool isPolygonOffsetFillEnabled() const;
void setPolygonOffsetParams(GLfloat factor, GLfloat units); void setPolygonOffsetParams(GLfloat factor, GLfloat units);
...@@ -367,7 +367,7 @@ public: ...@@ -367,7 +367,7 @@ public:
void setPackAlignment(GLint alignment); void setPackAlignment(GLint alignment);
GLint getPackAlignment() const; GLint getPackAlignment() const;
// These create and destroy methods are merely pass-throughs to // These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types // ResourceManager, which owns these object types
GLuint createBuffer(); GLuint createBuffer();
GLuint createTexture(); GLuint createTexture();
...@@ -419,6 +419,7 @@ public: ...@@ -419,6 +419,7 @@ public:
void clear(GLbitfield mask); void clear(GLbitfield mask);
void drawArrays(GLenum mode, GLint first, GLsizei count); void drawArrays(GLenum mode, GLint first, GLsizei count);
void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
void drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
void finish(); void finish();
void flush(); void flush();
...@@ -479,7 +480,7 @@ private: ...@@ -479,7 +480,7 @@ private:
VertexDataManager *mVertexDataManager; VertexDataManager *mVertexDataManager;
IndexDataManager *mIndexDataManager; IndexDataManager *mIndexDataManager;
bool lighting; bool lighting;
Light light[MAX_LIGHTS]; Light light[MAX_LIGHTS];
Color globalAmbient; Color globalAmbient;
...@@ -496,7 +497,7 @@ private: ...@@ -496,7 +497,7 @@ private:
bool mInvalidFramebufferOperation; bool mInvalidFramebufferOperation;
bool mHasBeenCurrent; bool mHasBeenCurrent;
// state caching flags // state caching flags
bool mDepthStateDirty; bool mDepthStateDirty;
bool mMaskStateDirty; bool mMaskStateDirty;
......
...@@ -35,6 +35,10 @@ Texture::Texture(GLuint name) : egl::Texture(name) ...@@ -35,6 +35,10 @@ Texture::Texture(GLuint name) : egl::Texture(name)
mWrapS = GL_REPEAT; mWrapS = GL_REPEAT;
mWrapT = GL_REPEAT; mWrapT = GL_REPEAT;
mMaxAnisotropy = 1.0f; mMaxAnisotropy = 1.0f;
cropRectU = 0;
cropRectV = 0;
cropRectW = 0;
cropRectH = 0;
resource = new sw::Resource(0); resource = new sw::Resource(0);
} }
...@@ -135,7 +139,7 @@ bool Texture::setMaxAnisotropy(float textureMaxAnisotropy) ...@@ -135,7 +139,7 @@ bool Texture::setMaxAnisotropy(float textureMaxAnisotropy)
{ {
return false; return false;
} }
if(mMaxAnisotropy != textureMaxAnisotropy) if(mMaxAnisotropy != textureMaxAnisotropy)
{ {
mMaxAnisotropy = textureMaxAnisotropy; mMaxAnisotropy = textureMaxAnisotropy;
...@@ -144,6 +148,14 @@ bool Texture::setMaxAnisotropy(float textureMaxAnisotropy) ...@@ -144,6 +148,14 @@ bool Texture::setMaxAnisotropy(float textureMaxAnisotropy)
return true; return true;
} }
void Texture::setCropRect(GLint u, GLint v, GLint w, GLint h)
{
cropRectU = u;
cropRectV = v;
cropRectW = w;
cropRectH = h;
}
GLenum Texture::getMinFilter() const GLenum Texture::getMinFilter() const
{ {
return mMinFilter; return mMinFilter;
...@@ -169,6 +181,26 @@ GLfloat Texture::getMaxAnisotropy() const ...@@ -169,6 +181,26 @@ GLfloat Texture::getMaxAnisotropy() const
return mMaxAnisotropy; return mMaxAnisotropy;
} }
GLint Texture::getCropRectU() const
{
return cropRectU;
}
GLint Texture::getCropRectV() const
{
return cropRectV;
}
GLint Texture::getCropRectW() const
{
return cropRectW;
}
GLint Texture::getCropRectH() const
{
return cropRectH;
}
egl::Image *Texture::createSharedImage(GLenum target, unsigned int level) egl::Image *Texture::createSharedImage(GLenum target, unsigned int level)
{ {
egl::Image *image = getRenderTarget(target, level); // Increments reference count egl::Image *image = getRenderTarget(target, level); // Increments reference count
...@@ -251,7 +283,7 @@ void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL ...@@ -251,7 +283,7 @@ void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL
bool Texture::copy(egl::Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, egl::Image *dest) bool Texture::copy(egl::Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, egl::Image *dest)
{ {
Device *device = getDevice(); Device *device = getDevice();
sw::SliceRect destRect(xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0), 0); sw::SliceRect destRect(xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0), 0);
sw::SliceRect sourceSliceRect(sourceRect); sw::SliceRect sourceSliceRect(sourceRect);
bool success = device->stretchRect(source, &sourceSliceRect, dest, &destRect, false); bool success = device->stretchRect(source, &sourceSliceRect, dest, &destRect, false);
...@@ -319,8 +351,8 @@ Texture2D::~Texture2D() ...@@ -319,8 +351,8 @@ Texture2D::~Texture2D()
mColorbufferProxy = NULL; mColorbufferProxy = NULL;
} }
// We need to maintain a count of references to renderbuffers acting as // We need to maintain a count of references to renderbuffers acting as
// proxies for this texture, so that we do not attempt to use a pointer // proxies for this texture, so that we do not attempt to use a pointer
// to a renderbuffer proxy which has been deleted. // to a renderbuffer proxy which has been deleted.
void Texture2D::addProxyRef(const Renderbuffer *proxy) void Texture2D::addProxyRef(const Renderbuffer *proxy)
{ {
...@@ -633,7 +665,7 @@ void Texture2D::generateMipmaps() ...@@ -633,7 +665,7 @@ void Texture2D::generateMipmaps()
} }
unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight())); unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight()));
for(unsigned int i = 1; i <= q; i++) for(unsigned int i = 1; i <= q; i++)
{ {
if(image[i]) if(image[i])
...@@ -742,7 +774,7 @@ extern "C" ...@@ -742,7 +774,7 @@ extern "C"
ERR("Invalid parameters"); ERR("Invalid parameters");
return 0; return 0;
} }
bool lockable = true; bool lockable = true;
switch(format) switch(format)
......
...@@ -65,12 +65,17 @@ public: ...@@ -65,12 +65,17 @@ public:
bool setWrapS(GLenum wrap); bool setWrapS(GLenum wrap);
bool setWrapT(GLenum wrap); bool setWrapT(GLenum wrap);
bool setMaxAnisotropy(GLfloat textureMaxAnisotropy); bool setMaxAnisotropy(GLfloat textureMaxAnisotropy);
void setCropRect(GLint u, GLint v, GLint w, GLint h);
GLenum getMinFilter() const; GLenum getMinFilter() const;
GLenum getMagFilter() const; GLenum getMagFilter() const;
GLenum getWrapS() const; GLenum getWrapS() const;
GLenum getWrapT() const; GLenum getWrapT() const;
GLfloat getMaxAnisotropy() const; GLfloat getMaxAnisotropy() const;
GLint getCropRectU() const;
GLint getCropRectV() const;
GLint getCropRectW() const;
GLint getCropRectH() const;
virtual GLsizei getWidth(GLenum target, GLint level) const = 0; virtual GLsizei getWidth(GLenum target, GLint level) const = 0;
virtual GLsizei getHeight(GLenum target, GLint level) const = 0; virtual GLsizei getHeight(GLenum target, GLint level) const = 0;
...@@ -106,6 +111,10 @@ protected: ...@@ -106,6 +111,10 @@ protected:
GLenum mWrapS; GLenum mWrapS;
GLenum mWrapT; GLenum mWrapT;
GLfloat mMaxAnisotropy; GLfloat mMaxAnisotropy;
GLint cropRectU;
GLint cropRectV;
GLint cropRectW;
GLint cropRectH;
sw::Resource *resource; sw::Resource *resource;
}; };
...@@ -156,9 +165,9 @@ protected: ...@@ -156,9 +165,9 @@ protected:
bool isMipmapComplete() const; bool isMipmapComplete() const;
egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
egl::Surface *mSurface; egl::Surface *mSurface;
// A specific internal reference count is kept for colorbuffer proxy references, // A specific internal reference count is kept for colorbuffer proxy references,
// because, as the renderbuffer acting as proxy will maintain a binding pointer // because, as the renderbuffer acting as proxy will maintain a binding pointer
// back to this texture, there would be a circular reference if we used a binding // back to this texture, there would be a circular reference if we used a binding
......
...@@ -1780,7 +1780,7 @@ void GL_APIENTRY glFogf(GLenum pname, GLfloat param) ...@@ -1780,7 +1780,7 @@ void GL_APIENTRY glFogf(GLenum pname, GLfloat param)
default: default:
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
} }
} }
void GL_APIENTRY glFogfv(GLenum pname, const GLfloat *params) void GL_APIENTRY glFogfv(GLenum pname, const GLfloat *params)
...@@ -1830,7 +1830,7 @@ void GL_APIENTRY glFogfv(GLenum pname, const GLfloat *params) ...@@ -1830,7 +1830,7 @@ void GL_APIENTRY glFogfv(GLenum pname, const GLfloat *params)
default: default:
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
} }
} }
void GL_APIENTRY glFogx(GLenum pname, GLfixed param) void GL_APIENTRY glFogx(GLenum pname, GLfixed param)
...@@ -3018,7 +3018,7 @@ void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, G ...@@ -3018,7 +3018,7 @@ void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, G
{ {
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
es1::Context *context = es1::getContext(); es1::Context *context = es1::getContext();
if(context) if(context)
...@@ -3340,7 +3340,7 @@ void GL_APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) ...@@ -3340,7 +3340,7 @@ void GL_APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param)
UNIMPLEMENTED(); UNIMPLEMENTED();
break; break;
case GL_ADD: case GL_ADD:
context->setTextureEnvMode((GLenum)param); context->setTextureEnvMode((GLenum)param);
break; break;
case GL_ADD_SIGNED: case GL_ADD_SIGNED:
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -3640,9 +3640,6 @@ void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) ...@@ -3640,9 +3640,6 @@ void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
break; break;
case GL_TEXTURE_CROP_RECT_OES:
UNIMPLEMENTED();
break;
default: default:
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
...@@ -3651,7 +3648,40 @@ void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) ...@@ -3651,7 +3648,40 @@ void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params) void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
{ {
glTexParameteri(target, pname, *params); TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = 0x%0.8p)", target, pname, params);
switch(pname)
{
case GL_TEXTURE_CROP_RECT_OES:
break;
default:
return glTexParameteri(target, pname, params[0]);
}
es1::Context *context = es1::getContext();
if(context)
{
es1::Texture *texture;
switch(target)
{
case GL_TEXTURE_2D:
texture = context->getTexture2D();
break;
default:
return error(GL_INVALID_ENUM);
}
switch(pname)
{
case GL_TEXTURE_CROP_RECT_OES:
texture->setCropRect(params[0], params[1], params[2], params[3]);
break;
default:
return error(GL_INVALID_ENUM);
}
}
} }
void GL_APIENTRY glTexParameterx(GLenum target, GLenum pname, GLfixed param) void GL_APIENTRY glTexParameterx(GLenum target, GLenum pname, GLfixed param)
...@@ -3816,7 +3846,19 @@ void GL_APIENTRY glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, G ...@@ -3816,7 +3846,19 @@ void GL_APIENTRY glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, G
void GL_APIENTRY glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) void GL_APIENTRY glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height)
{ {
UNIMPLEMENTED(); TRACE("(GLint x = %d, GLint y = %d, GLint z = %d, GLint width = %d, GLint height = %d)", x, y, z, width, height);
if(width <= 0 || height <= 0)
{
return error(GL_INVALID_VALUE);
}
es1::Context *context = es1::getContext();
if(context)
{
context->drawTexture(x, y, z, width, height);
}
} }
void GL_APIENTRY glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) void GL_APIENTRY glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
......
...@@ -211,18 +211,18 @@ namespace es2 ...@@ -211,18 +211,18 @@ namespace es2
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_ETC1_RGB8_OES: case GL_ETC1_RGB8_OES:
case GL_COMPRESSED_R11_EAC: case GL_COMPRESSED_R11_EAC:
case GL_COMPRESSED_SIGNED_R11_EAC: case GL_COMPRESSED_SIGNED_R11_EAC:
case GL_COMPRESSED_RGB8_ETC2: case GL_COMPRESSED_RGB8_ETC2:
case GL_COMPRESSED_SRGB8_ETC2: case GL_COMPRESSED_SRGB8_ETC2:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f); return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
case GL_COMPRESSED_RG11_EAC: case GL_COMPRESSED_RG11_EAC:
case GL_COMPRESSED_SIGNED_RG11_EAC: case GL_COMPRESSED_SIGNED_RG11_EAC:
case GL_COMPRESSED_RGBA8_ETC2_EAC: case GL_COMPRESSED_RGBA8_ETC2_EAC:
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f); return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
default: default:
......
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