Commit 0df813c3 by Lingfeng Yang Committed by Commit Bot

GLES1: GL_OES_draw_texture

BUG=angleproject:2306 This implements GL_OES_draw_texture using a few bits of new state in the renderer and adding a code path for it in the shader, using gl_VertexID to draw the quad backing the texture draw. This allows us to avoid allocating a separate vertex array for the texture draw and reuses the current shader as much as possible, plugging in to the existing multitexturing pipeline. - Add unit test and sample - No new test expectations, but advertising GL_OES_draw_texture makes the DrawTex GLES1 conformance test non-trivial and actually test glDrawTex*. Change-Id: I1485098249fe44d46a01cab4bb7b2c39d0492923 Reviewed-on: https://chromium-review.googlesource.com/1135930Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Lingfeng Yang <lfy@google.com>
parent 94c91a95
......@@ -197,6 +197,12 @@ angle_sample("gles1_flat_shading") {
]
}
angle_sample("gles1_draw_texture") {
sources = [
"gles1/DrawTexture.cpp",
]
}
group("all") {
testonly = true
deps = [
......
//
// Copyright 2018 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.
//
// Based on Simple_Texture2D.c from
// Book: OpenGL(R) ES 2.0 Programming Guide
// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10: 0321502795
// ISBN-13: 9780321502797
// Publisher: Addison-Wesley Professional
// URLs: http://safari.informit.com/9780321563835
// http://www.opengles-book.com
#include "SampleApplication.h"
#include "shader_utils.h"
#include "texture_utils.h"
#include "util/system_utils.h"
#include <GLES/gl.h>
#include <GLES/glext.h>
class GLES1DrawTextureSample : public SampleApplication
{
public:
GLES1DrawTextureSample(int argc, char **argv)
: SampleApplication("GLES1DrawTexture", argc, argv, 1, 0, 1280, 800)
{
}
bool initialize() override
{
// Load the texture
mTexture = CreateSimpleTexture2D();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mTexture);
GLint crop[4] = {0, 0, 2, 2};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
return true;
}
void destroy() override { glDeleteTextures(1, &mTexture); }
void draw() override
{
glClear(GL_COLOR_BUFFER_BIT);
GLint windowWidth = getWindow()->getWidth();
GLint windowHeight = getWindow()->getHeight();
glDrawTexiOES(mX, mY, 0, mWidth, mHeight);
glDrawTexiOES(windowWidth - mX, mY, 0, mWidth, mHeight);
glDrawTexiOES(mX, windowHeight - mY, 0, mWidth, mHeight);
glDrawTexiOES(windowWidth - mX, windowHeight - mY, 0, mWidth, mHeight);
mX += mReverseX ? -1 : 1;
mY += mReverseY ? -1 : 1;
if (mX + mWidth >= windowWidth)
mReverseX = true;
if (mX < 0)
mReverseX = false;
if (mY + mHeight >= windowHeight)
mReverseY = true;
if (mY < 0)
mReverseY = false;
++mWidth;
++mHeight;
if (mWidth >= windowWidth)
mWidth = 0;
if (mHeight >= windowHeight)
mHeight = 0;
angle::Sleep(16);
}
private:
// Texture handle
GLuint mTexture = 0;
// Draw texture coordinates and dimensions to loop through
GLint mX = 0;
GLint mY = 0;
GLint mWidth = 0;
GLint mHeight = 0;
bool mReverseX = false;
bool mReverseY = false;
};
int main(int argc, char **argv)
{
GLES1DrawTextureSample app(argc, argv);
return app.run();
}
......@@ -1153,6 +1153,17 @@ inline int32_t WrappingMul(int32_t lhs, int32_t rhs)
return static_cast<int32_t>(resultWide);
}
inline float scaleScreenDimensionToNdc(float dimensionScreen, float viewportDimension)
{
return 2.0f * dimensionScreen / viewportDimension;
}
inline float scaleScreenCoordinateToNdc(float coordinateScreen, float viewportDimension)
{
float halfShifted = coordinateScreen / viewportDimension;
return 2.0f * (halfShifted - 0.5f);
}
} // namespace gl
namespace rx
......
......@@ -246,6 +246,7 @@ Extensions::Extensions()
pointSizeArray(false),
textureCubeMap(false),
pointSprite(false),
drawTexture(false),
explicitContextGles1(false),
explicitContext(false),
parallelShaderCompile(false)
......@@ -857,6 +858,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArray);
map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMap);
map["GL_OES_point_sprite"] = enableableExtension(&Extensions::pointSprite);
map["GL_OES_draw_texture"] = enableableExtension(&Extensions::drawTexture);
// clang-format on
return map;
......
......@@ -415,6 +415,8 @@ struct Extensions
bool textureCubeMap;
// GL_OES_point_sprite
bool pointSprite;
// GL_OES_draw_texture
bool drawTexture;
// EGL_ANGLE_explicit_context GL subextensions
// GL_ANGLE_explicit_context_gles1
......
......@@ -3091,9 +3091,10 @@ Extensions Context::generateSupportedExtensions() const
if (getClientVersion() < ES_2_0)
{
// Default extensions for GLES1
supportedExtensions.pointSizeArray = true;
supportedExtensions.textureCubeMap = true;
supportedExtensions.pointSprite = true;
supportedExtensions.pointSizeArray = true;
supportedExtensions.textureCubeMap = true;
supportedExtensions.pointSprite = true;
supportedExtensions.drawTexture = true;
supportedExtensions.parallelShaderCompile = false;
}
......
......@@ -576,42 +576,54 @@ void Context::vertexPointer(GLint size, GLenum type, GLsizei stride, const void
// GL_OES_draw_texture
void Context::drawTexf(float x, float y, float z, float width, float height)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, x, y, z, width, height);
}
void Context::drawTexfv(const GLfloat *coords)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, coords[0], coords[1], coords[2], coords[3],
coords[4]);
}
void Context::drawTexi(GLint x, GLint y, GLint z, GLint width, GLint height)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, static_cast<GLfloat>(x), static_cast<GLfloat>(y),
static_cast<GLfloat>(z), static_cast<GLfloat>(width),
static_cast<GLfloat>(height));
}
void Context::drawTexiv(const GLint *coords)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, static_cast<GLfloat>(coords[0]),
static_cast<GLfloat>(coords[1]), static_cast<GLfloat>(coords[2]),
static_cast<GLfloat>(coords[3]), static_cast<GLfloat>(coords[4]));
}
void Context::drawTexs(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, static_cast<GLfloat>(x), static_cast<GLfloat>(y),
static_cast<GLfloat>(z), static_cast<GLfloat>(width),
static_cast<GLfloat>(height));
}
void Context::drawTexsv(const GLshort *coords)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, static_cast<GLfloat>(coords[0]),
static_cast<GLfloat>(coords[1]), static_cast<GLfloat>(coords[2]),
static_cast<GLfloat>(coords[3]), static_cast<GLfloat>(coords[4]));
}
void Context::drawTexx(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, FixedToFloat(x), FixedToFloat(y), FixedToFloat(z),
FixedToFloat(width), FixedToFloat(height));
}
void Context::drawTexxv(const GLfixed *coords)
{
UNIMPLEMENTED();
mGLES1Renderer->drawTexture(this, &mGLState, FixedToFloat(coords[0]), FixedToFloat(coords[1]),
FixedToFloat(coords[2]), FixedToFloat(coords[3]),
FixedToFloat(coords[4]));
}
// GL_OES_matrix_palette
......
......@@ -185,6 +185,8 @@ ERRMSG(NegativeStride, "Cannot have negative stride.");
ERRMSG(NoActiveComputeShaderStage, "No active compute shader stage in this program.");
ERRMSG(NoActiveGeometryShaderStage, "No active geometry shader stage in this program.");
ERRMSG(NoActiveProgramWithComputeShader, "No active program for the compute shader stage.");
ERRMSG(NonPositiveDrawTextureDimension,
"Both width and height argument of drawn texture must be positive.");
ERRMSG(NoSuchPath, "No such path object.");
ERRMSG(NoTransformFeedbackOutputVariables,
"The active program has specified no output variables to record.");
......
......@@ -117,6 +117,8 @@ Error GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State
std::vector<int> tex2DFormats = {GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA};
Vec4Uniform *cropRectBuffer = uniformBuffers.texCropRects.data();
for (int i = 0; i < kTexUnitCount; i++)
{
// GL_OES_cube_map allows only one of TEXTURE_2D / TEXTURE_CUBE_MAP
......@@ -146,6 +148,21 @@ Error GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State
{
tex2DFormats[i] = gl::GetUnsizedFormat(
curr2DTexture->getFormat(TextureTarget::_2D, 0).info->internalFormat);
const gl::Rectangle &cropRect = curr2DTexture->getCrop();
GLfloat textureWidth =
static_cast<GLfloat>(curr2DTexture->getWidth(TextureTarget::_2D, 0));
GLfloat textureHeight =
static_cast<GLfloat>(curr2DTexture->getHeight(TextureTarget::_2D, 0));
if (textureWidth > 0.0f && textureHeight > 0.0f)
{
cropRectBuffer[i][0] = cropRect.x / textureWidth;
cropRectBuffer[i][1] = cropRect.y / textureHeight;
cropRectBuffer[i][2] = cropRect.width / textureWidth;
cropRectBuffer[i][3] = cropRect.height / textureHeight;
}
}
}
......@@ -157,6 +174,9 @@ Error GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State
setUniform1iv(programObject, mProgramState.textureFormatLoc, kTexUnitCount,
tex2DFormats.data());
setUniform4fv(programObject, mProgramState.drawTextureNormalizedCropRectLoc, kTexUnitCount,
reinterpret_cast<GLfloat *>(cropRectBuffer));
for (int i = 0; i < kTexUnitCount; i++)
{
const auto &env = gles1State.textureEnvironment(i);
......@@ -363,6 +383,14 @@ Error GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State
pointParams.pointDistanceAttenuation.data());
}
// Draw texture
{
setUniform1i(programObject, mProgramState.enableDrawTextureLoc,
mDrawTextureEnabled ? 1 : 0);
setUniform4fv(programObject, mProgramState.drawTextureCoordsLoc, 1, mDrawTextureCoords);
setUniform2fv(programObject, mProgramState.drawTextureDimsLoc, 1, mDrawTextureDims);
}
// None of those are changes in sampler, so there is no need to set the GL_PROGRAM dirty.
// Otherwise, put the dirtying here.
......@@ -418,6 +446,48 @@ AttributesMask GLES1Renderer::getVertexArraysAttributeMask(const State *glState)
return res;
}
void GLES1Renderer::drawTexture(Context *context,
State *glState,
float x,
float y,
float z,
float width,
float height)
{
// get viewport
const gl::Rectangle &viewport = glState->getViewport();
// Translate from viewport to NDC for feeding the shader.
// Recenter, rescale. (e.g., [0, 0, 1080, 1920] -> [-1, -1, 1, 1])
float xNdc = scaleScreenCoordinateToNdc(x, static_cast<GLfloat>(viewport.width));
float yNdc = scaleScreenCoordinateToNdc(y, static_cast<GLfloat>(viewport.height));
float wNdc = scaleScreenDimensionToNdc(width, static_cast<GLfloat>(viewport.width));
float hNdc = scaleScreenDimensionToNdc(height, static_cast<GLfloat>(viewport.height));
float zNdc = 2.0f * clamp(z, 0.0f, 1.0f) - 1.0f;
mDrawTextureCoords[0] = xNdc;
mDrawTextureCoords[1] = yNdc;
mDrawTextureCoords[2] = zNdc;
mDrawTextureDims[0] = wNdc;
mDrawTextureDims[1] = hNdc;
mDrawTextureEnabled = true;
AttributesMask prevAttributesMask = getVertexArraysAttributeMask(glState);
setAttributesEnabled(context, glState, AttributesMask());
context->gatherParams<EntryPoint::DrawArrays>(PrimitiveMode::Triangles, 0, 6);
context->drawArrays(PrimitiveMode::Triangles, 0, 6);
setAttributesEnabled(context, glState, prevAttributesMask);
mDrawTextureEnabled = false;
}
Shader *GLES1Renderer::getShader(GLuint handle) const
{
return mShaderPrograms->getShader(handle);
......@@ -656,6 +726,12 @@ Error GLES1Renderer::initializeRendererProgram(Context *context, State *glState)
programObject->getUniformLocation("point_distance_attenuation");
mProgramState.pointSpriteEnabledLoc = programObject->getUniformLocation("point_sprite_enabled");
mProgramState.enableDrawTextureLoc = programObject->getUniformLocation("enable_draw_texture");
mProgramState.drawTextureCoordsLoc = programObject->getUniformLocation("draw_texture_coords");
mProgramState.drawTextureDimsLoc = programObject->getUniformLocation("draw_texture_dims");
mProgramState.drawTextureNormalizedCropRectLoc =
programObject->getUniformLocation("draw_texture_normalized_crop_rect");
glState->setProgram(context, programObject);
for (int i = 0; i < kTexUnitCount; i++)
......@@ -718,6 +794,16 @@ void GLES1Renderer::setUniform3fv(Program *programObject,
programObject->setUniform3fv(loc, count, value);
}
void GLES1Renderer::setUniform2fv(Program *programObject,
GLint loc,
GLint count,
const GLfloat *value)
{
if (loc == -1)
return;
programObject->setUniform2fv(loc, count, value);
}
void GLES1Renderer::setUniform1f(Program *programObject, GLint loc, GLfloat value)
{
if (loc == -1)
......@@ -735,4 +821,46 @@ void GLES1Renderer::setUniform1fv(Program *programObject,
programObject->setUniform1fv(loc, count, value);
}
void GLES1Renderer::setAttributesEnabled(Context *context, State *glState, AttributesMask mask)
{
GLES1State &gles1 = glState->gles1();
ClientVertexArrayType nonTexcoordArrays[] = {
ClientVertexArrayType::Vertex, ClientVertexArrayType::Normal, ClientVertexArrayType::Color,
ClientVertexArrayType::PointSize,
};
for (const ClientVertexArrayType attrib : nonTexcoordArrays)
{
int index = vertexArrayIndex(attrib, glState);
if (mask.test(index))
{
gles1.setClientStateEnabled(attrib, true);
context->enableVertexAttribArray(index);
}
else
{
gles1.setClientStateEnabled(attrib, false);
context->disableVertexAttribArray(index);
}
}
for (unsigned int i = 0; i < kTexUnitCount; i++)
{
int index = TexCoordArrayIndex(i);
if (mask.test(index))
{
gles1.setTexCoordArrayEnabled(i, true);
context->enableVertexAttribArray(index);
}
else
{
gles1.setTexCoordArrayEnabled(i, false);
context->disableVertexAttribArray(index);
}
}
}
} // namespace gl
......@@ -41,6 +41,14 @@ class GLES1Renderer final : angle::NonCopyable
static int TexCoordArrayIndex(unsigned int unit);
AttributesMask getVertexArraysAttributeMask(const State *glState) const;
void drawTexture(Context *context,
State *glState,
float x,
float y,
float z,
float width,
float height);
private:
using Mat4Uniform = float[16];
using Vec4Uniform = float[4];
......@@ -70,9 +78,12 @@ class GLES1Renderer final : angle::NonCopyable
const GLfloat *value);
void setUniform4fv(Program *programObject, GLint loc, GLint count, const GLfloat *value);
void setUniform3fv(Program *programObject, GLint loc, GLint count, const GLfloat *value);
void setUniform2fv(Program *programObject, GLint loc, GLint count, const GLfloat *value);
void setUniform1f(Program *programObject, GLint loc, GLfloat value);
void setUniform1fv(Program *programObject, GLint loc, GLint count, const GLfloat *value);
void setAttributesEnabled(Context *context, State *glState, AttributesMask mask);
static constexpr int kTexUnitCount = 4;
static constexpr int kLightCount = 8;
static constexpr int kClipPlaneCount = 6;
......@@ -175,6 +186,12 @@ class GLES1Renderer final : angle::NonCopyable
GLint pointSizeMaxLoc;
GLint pointDistanceAttenuationLoc;
GLint pointSpriteEnabledLoc;
// Draw texture
GLint enableDrawTextureLoc;
GLint drawTextureCoordsLoc;
GLint drawTextureDimsLoc;
GLint drawTextureNormalizedCropRectLoc;
};
struct GLES1UniformBuffers
......@@ -220,10 +237,17 @@ class GLES1Renderer final : angle::NonCopyable
// Clip planes
std::array<GLint, kClipPlaneCount> clipPlaneEnables;
std::array<Vec4Uniform, kClipPlaneCount> clipPlanes;
// Texture crop rectangles
std::array<Vec4Uniform, kTexUnitCount> texCropRects;
};
GLES1UniformBuffers mUniformBuffers;
GLES1ProgramState mProgramState;
bool mDrawTextureEnabled = false;
GLfloat mDrawTextureCoords[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GLfloat mDrawTextureDims[2] = {0.0f, 0.0f};
};
} // namespace gl
......
......@@ -23,7 +23,7 @@ in vec4 texcoord3;
uniform mat4 projection;
uniform mat4 modelview;
uniform mat4 modelview_invtr;
uniform mat4 texture_matrix[4];
uniform mat4 texture_matrix[kMaxTexUnits];
uniform bool enable_rescale_normal;
uniform bool enable_normalize;
......@@ -35,21 +35,84 @@ uniform float point_size_min;
uniform float point_size_max;
uniform vec3 point_distance_attenuation;
// GL_OES_draw_texture uniforms/////////////////////////////////////////////////
uniform bool enable_draw_texture;
uniform vec4 draw_texture_coords;
uniform vec2 draw_texture_dims;
uniform vec4 draw_texture_normalized_crop_rect[kMaxTexUnits];
// Varyings/////////////////////////////////////////////////////////////////////
out vec4 pos_varying;
out vec3 normal_varying;
out vec4 color_varying;
flat out vec4 color_varying_flat;
out float pointsize_varying;
out vec4 texcoord0_varying;
out vec4 texcoord1_varying;
out vec4 texcoord2_varying;
out vec4 texcoord3_varying;
void main()
const vec4 drawTextureVertices[6] = vec4[](
vec4(0.0, 0.0, 0.0, 1.0),
vec4(1.0, 0.0, 0.0, 1.0),
vec4(1.0, 1.0, 0.0, 1.0),
vec4(0.0, 0.0, 0.0, 1.0),
vec4(1.0, 1.0, 0.0, 1.0),
vec4(0.0, 1.0, 0.0, 1.0));
vec4 drawTexturePosition(int vertexId)
{
float drawTexX = draw_texture_coords[0];
float drawTexY = draw_texture_coords[1];
float drawTexZ = draw_texture_coords[2];
float drawTexW = draw_texture_dims[0];
float drawTexH = draw_texture_dims[1];
return vec4(drawTexX, drawTexY, drawTexZ, 0.0) +
drawTextureVertices[vertexId] *
vec4(drawTexW, drawTexH, 1.0, 1.0);
}
vec4 drawTextureTexCoord(int vertexId, int textureUnit)
{
float texCropU = draw_texture_normalized_crop_rect[textureUnit].x;
float texCropV = draw_texture_normalized_crop_rect[textureUnit].y;
float texCropW = draw_texture_normalized_crop_rect[textureUnit].z;
float texCropH = draw_texture_normalized_crop_rect[textureUnit].w;
return vec4(texCropU, texCropV, 0.0, 0.0) +
drawTextureVertices[vertexId] *
vec4(texCropW, texCropH, 0.0, 0.0);
}
vec4 calcWorldPosition(vec4 posInput)
{
return modelview * posInput;
}
vec4 calcNdcFromWorldPosition(vec4 worldPos)
{
return projection * worldPos;
}
float calcPointSize(vec4 ndcPos)
{
float dist = length(ndcPos.z);
float attConst = point_distance_attenuation[0];
float attLinear = point_distance_attenuation[1];
float attQuad = point_distance_attenuation[2];
float attPart = attConst + attLinear * dist + attQuad * dist * dist;
float attPointSize = pointsize / pow(attPart, 0.5);
return clamp(attPointSize, point_size_min, point_size_max);
}
vec3 calcNormal(vec3 normalInput)
{
pos_varying = modelview * pos;
mat3 mvInvTr3 = mat3(modelview_invtr);
normal_varying = mvInvTr3 * normal;
mat3 mvInvTr3 = mat3(modelview_invtr);
vec3 result = mvInvTr3 * normalInput;
if (enable_rescale_normal)
{
......@@ -60,35 +123,64 @@ void main()
{
rescale = 1.0 / len;
}
normal_varying *= rescale;
result *= rescale;
}
if (enable_normalize)
{
normal_varying = normalize(normal_varying);
result = normalize(result);
}
return result;
}
void main()
{
color_varying = color;
color_varying_flat = color;
pointsize_varying = pointsize;
texcoord0_varying = texture_matrix[0] * texcoord0;
texcoord1_varying = texture_matrix[1] * texcoord1;
texcoord2_varying = texture_matrix[2] * texcoord2;
texcoord3_varying = texture_matrix[3] * texcoord3;
vec4 vertexPos = projection * modelview * pos;
gl_Position = vertexPos;
if (enable_draw_texture)
{
int vertexId = gl_VertexID;
vec4 posDrawTexture = drawTexturePosition(vertexId);
if (point_rasterization)
gl_Position = posDrawTexture;
pos_varying = posDrawTexture;
normal_varying = normal;
gl_PointSize = pointsize;
texcoord0_varying = drawTextureTexCoord(vertexId, 0);
texcoord1_varying = drawTextureTexCoord(vertexId, 1);
texcoord2_varying = drawTextureTexCoord(vertexId, 2);
texcoord3_varying = drawTextureTexCoord(vertexId, 3);
}
else
{
float dist = length(vertexPos.z);
float attConst = point_distance_attenuation[0];
float attLinear = point_distance_attenuation[1];
float attQuad = point_distance_attenuation[2];
float attPart = attConst + attLinear * dist + attQuad * dist * dist;
float attPointSize = pointsize / pow(attPart, 0.5);
vec4 worldPos = calcWorldPosition(pos);
vec4 ndcPos = calcNdcFromWorldPosition(worldPos);
gl_PointSize = clamp(attPointSize, point_size_min, point_size_max);
gl_Position = ndcPos;
pos_varying = worldPos;
normal_varying = calcNormal(normal);
// Avoid calculating point size stuff
// if we are not rendering points.
if (point_rasterization)
{
gl_PointSize = calcPointSize(ndcPos);
}
else
{
gl_PointSize = pointsize;
}
texcoord0_varying = texture_matrix[0] * texcoord0;
texcoord1_varying = texture_matrix[1] * texcoord1;
texcoord2_varying = texture_matrix[2] * texcoord2;
texcoord3_varying = texture_matrix[3] * texcoord3;
}
}
)";
......@@ -213,7 +305,6 @@ in vec4 pos_varying;
in vec3 normal_varying;
in vec4 color_varying;
flat in vec4 color_varying_flat;
in float pointsize_varying;
in vec4 texcoord0_varying;
in vec4 texcoord1_varying;
in vec4 texcoord2_varying;
......@@ -272,6 +363,10 @@ uniform vec4 clip_planes[kMaxClipPlanes];
uniform bool point_rasterization;
uniform bool point_sprite_enabled;
// GL_OES_draw_texture//////////////////////////////////////////////////////////
uniform bool enable_draw_texture;
// Outgoing fragment////////////////////////////////////////////////////////////
out vec4 frag_color;
......@@ -950,7 +1045,7 @@ vec4 textureFunction(int unit,
constexpr char kGLES1DrawFShaderMain[] = R"(
void main()
{
if (enable_clip_planes)
if (enable_clip_planes && !enable_draw_texture)
{
if (!doClipPlaneTest())
{
......
......@@ -290,6 +290,11 @@ void GLES1State::setClientStateEnabled(ClientVertexArrayType clientState, bool e
}
}
void GLES1State::setTexCoordArrayEnabled(unsigned int unit, bool enable)
{
mTexCoordArrayEnabled[unit] = enable;
}
bool GLES1State::isClientStateEnabled(ClientVertexArrayType clientState) const
{
switch (clientState)
......
......@@ -161,6 +161,7 @@ class GLES1State final : angle::NonCopyable
void multMatrix(const angle::Mat4 &m);
void setClientStateEnabled(ClientVertexArrayType clientState, bool enable);
void setTexCoordArrayEnabled(unsigned int unit, bool enable);
bool isClientStateEnabled(ClientVertexArrayType clientState) const;
bool isTexCoordArrayEnabled(unsigned int unit) const;
bool isTextureTargetEnabled(unsigned int unit, const TextureType type) const;
......
......@@ -595,6 +595,19 @@ bool ValidatePointSizeCommon(Context *context, GLfloat size)
return true;
}
bool ValidateDrawTexCommon(Context *context, float width, float height)
{
ANGLE_VALIDATE_IS_GLES1(context);
if (width <= 0.0f || height <= 0.0f)
{
ANGLE_VALIDATION_ERR(context, InvalidValue(), NonPositiveDrawTextureDimension);
return false;
}
return true;
}
} // namespace gl
namespace gl
......@@ -1302,26 +1315,24 @@ bool ValidateDrawTexfOES(Context *context,
GLfloat width,
GLfloat height)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, width, height);
}
bool ValidateDrawTexfvOES(Context *context, const GLfloat *coords)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, coords[3], coords[4]);
}
bool ValidateDrawTexiOES(Context *context, GLint x, GLint y, GLint z, GLint width, GLint height)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, static_cast<GLfloat>(width),
static_cast<GLfloat>(height));
}
bool ValidateDrawTexivOES(Context *context, const GLint *coords)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, static_cast<GLfloat>(coords[3]),
static_cast<GLfloat>(coords[4]));
}
bool ValidateDrawTexsOES(Context *context,
......@@ -1331,14 +1342,14 @@ bool ValidateDrawTexsOES(Context *context,
GLshort width,
GLshort height)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, static_cast<GLfloat>(width),
static_cast<GLfloat>(height));
}
bool ValidateDrawTexsvOES(Context *context, const GLshort *coords)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, static_cast<GLfloat>(coords[3]),
static_cast<GLfloat>(coords[4]));
}
bool ValidateDrawTexxOES(Context *context,
......@@ -1348,14 +1359,12 @@ bool ValidateDrawTexxOES(Context *context,
GLfixed width,
GLfixed height)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, FixedToFloat(width), FixedToFloat(height));
}
bool ValidateDrawTexxvOES(Context *context, const GLfixed *coords)
{
UNIMPLEMENTED();
return true;
return ValidateDrawTexCommon(context, FixedToFloat(coords[3]), FixedToFloat(coords[4]));
}
bool ValidateCurrentPaletteMatrixOES(Context *context, GLuint matrixpaletteindex)
......
......@@ -56,6 +56,7 @@
'<(angle_path)/src/tests/gl_tests/gles1/CurrentColorTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/CurrentNormalTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/CurrentTextureCoordsTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/DrawTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/FogTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/MaterialsTest.cpp',
'<(angle_path)/src/tests/gl_tests/gles1/MatrixBuiltinsTest.cpp',
......
//
// Copyright 2018 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.
//
// DrawTextureTest.cpp: Tests basic usage of glDrawTex*.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include <memory>
#include <vector>
using namespace angle;
class DrawTextureTest : public ANGLETest
{
protected:
DrawTextureTest()
{
setWindowWidth(32);
setWindowHeight(32);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
}
void SetUp() override
{
ANGLETest::SetUp();
mTexture.reset(new GLTexture());
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mTexture->get());
}
void TearDown() override
{
mTexture.reset();
ANGLETest::TearDown();
}
std::unique_ptr<GLTexture> mTexture;
};
// Negative test for invalid width/height values.
TEST_P(DrawTextureTest, NegativeValue)
{
glDrawTexiOES(0, 0, 0, 0, 0);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glDrawTexiOES(0, 0, 0, -1, 0);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glDrawTexiOES(0, 0, 0, 0, -1);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glDrawTexiOES(0, 0, 0, -1, -1);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
}
// Basic draw.
TEST_P(DrawTextureTest, Basic)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
glDrawTexiOES(0, 0, 0, 1, 1);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Tests that odd viewport dimensions are handled correctly.
// If the viewport dimension is even, then the incorrect way
// of getting the center screen coordinate by dividing by 2 and
// converting to integer will work in that case, but not if
// the viewport dimension is odd.
TEST_P(DrawTextureTest, CorrectNdcForOddViewportDimensions)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// clang-format off
std::array<GLColor, 2> textureData = {
GLColor::green, GLColor::green
};
// clang-format on
glViewport(0, 0, 3, 3);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());
GLint cropRect[] = {0, 0, 2, 1};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
EXPECT_GL_NO_ERROR();
GLint x = 1;
GLint y = 1;
glDrawTexiOES(x, y, 0, 2, 1);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(x + 1, y, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(x, y + 1, GLColor::black);
EXPECT_PIXEL_COLOR_EQ(x + 1, y + 1, GLColor::black);
EXPECT_PIXEL_COLOR_EQ(x + 2, y, GLColor::black);
EXPECT_PIXEL_COLOR_EQ(x + 3, y, GLColor::black);
}
// Tests that vertex attributes enabled with fewer than 6 verts do not cause a crash.
TEST_P(DrawTextureTest, VertexAttributesNoCrash)
{
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0, &GLColor::white);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
EXPECT_GL_NO_ERROR();
glDrawTexiOES(0, 0, 0, 1, 1);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Tests that the color array, if enabled, is not used as the vertex color.
TEST_P(DrawTextureTest, ColorArrayNotUsed)
{
glEnableClientState(GL_COLOR_ARRAY);
// This color is set to black on purpose to ensure that the color in the upcoming vertex array
// is not used in the texture draw. If it is used, then the texture we want to read will be
// modulated with the color in the vertex array instead of GL_CURRENT_COLOR (which at the moment
// is white (1.0, 1.0, 1.0, 1.0).
glColorPointer(4, GL_FLOAT, 0, &GLColor::black);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
EXPECT_GL_NO_ERROR();
glDrawTexiOES(0, 0, 0, 1, 1);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
ANGLE_INSTANTIATE_TEST(DrawTextureTest, ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES());
......@@ -479,6 +479,7 @@ TEST_P(GLES1ConformanceTest, ZBFunc)
TEST_P(GLES1ConformanceTest, DrawTex)
{
ASSERT_TRUE(extensionEnabled("GL_OES_draw_texture"));
ASSERT_NE(CONFORMANCE_TEST_ERROR, DrawTexExec());
}
......
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