1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // GLES1Renderer.cpp: Implements the GLES1Renderer renderer.
8
9 #include "libANGLE/GLES1Renderer.h"
10
11 #include <string.h>
12 #include <iterator>
13 #include <sstream>
14 #include <vector>
15
16 #include "common/hash_utils.h"
17 #include "libANGLE/Context.h"
18 #include "libANGLE/Context.inl.h"
19 #include "libANGLE/Program.h"
20 #include "libANGLE/ResourceManager.h"
21 #include "libANGLE/Shader.h"
22 #include "libANGLE/State.h"
23 #include "libANGLE/renderer/ContextImpl.h"
24
25 namespace
26 {
27 #include "libANGLE/GLES1Shaders.inc"
28 } // anonymous namespace
29
30 namespace gl
31 {
32 GLES1ShaderState::GLES1ShaderState() = default;
33 GLES1ShaderState::~GLES1ShaderState() = default;
GLES1ShaderState(const GLES1ShaderState & other)34 GLES1ShaderState::GLES1ShaderState(const GLES1ShaderState &other)
35 {
36 memcpy(this, &other, sizeof(GLES1ShaderState));
37 }
38
operator ==(const GLES1ShaderState & a,const GLES1ShaderState & b)39 bool operator==(const GLES1ShaderState &a, const GLES1ShaderState &b)
40 {
41 return memcmp(&a, &b, sizeof(GLES1ShaderState)) == 0;
42 }
operator !=(const GLES1ShaderState & a,const GLES1ShaderState & b)43 bool operator!=(const GLES1ShaderState &a, const GLES1ShaderState &b)
44 {
45 return !(a == b);
46 }
47
hash() const48 size_t GLES1ShaderState::hash() const
49 {
50 return angle::ComputeGenericHash(*this);
51 }
52
GLES1Renderer()53 GLES1Renderer::GLES1Renderer() : mRendererProgramInitialized(false) {}
54
onDestroy(Context * context,State * state)55 void GLES1Renderer::onDestroy(Context *context, State *state)
56 {
57 if (mRendererProgramInitialized)
58 {
59 (void)state->setProgram(context, 0);
60
61 for (const auto &iter : mUberShaderState)
62 {
63 const GLES1UberShaderState &UberShaderState = iter.second;
64 mShaderPrograms->deleteProgram(context, {UberShaderState.programState.program});
65 }
66 mShaderPrograms->release(context);
67 mShaderPrograms = nullptr;
68 mRendererProgramInitialized = false;
69 }
70 }
71
72 GLES1Renderer::~GLES1Renderer() = default;
73
prepareForDraw(PrimitiveMode mode,Context * context,State * glState)74 angle::Result GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State *glState)
75 {
76 GLES1State &gles1State = glState->gles1();
77
78 GLES1ShaderState::BoolTexArray &tex2DEnables = mShaderState.tex2DEnables;
79 GLES1ShaderState::BoolTexArray &texCubeEnables = mShaderState.texCubeEnables;
80 GLES1ShaderState::IntTexArray &tex2DFormats = mShaderState.tex2DFormats;
81
82 for (int i = 0; i < kTexUnitCount; i++)
83 {
84 // GL_OES_cube_map allows only one of TEXTURE_2D / TEXTURE_CUBE_MAP
85 // to be enabled per unit, thankfully. From the extension text:
86 //
87 // -- Section 3.8.10 "Texture Application"
88 //
89 // Replace the beginning sentences of the first paragraph (page 138)
90 // with:
91 //
92 // "Texturing is enabled or disabled using the generic Enable
93 // and Disable commands, respectively, with the symbolic constants
94 // TEXTURE_2D or TEXTURE_CUBE_MAP_OES to enable the two-dimensional or cube
95 // map texturing respectively. If the cube map texture and the two-
96 // dimensional texture are enabled, then cube map texturing is used. If
97 // texturing is disabled, a rasterized fragment is passed on unaltered to the
98 // next stage of the GL (although its texture coordinates may be discarded).
99 // Otherwise, a texture value is found according to the parameter values of
100 // the currently bound texture image of the appropriate dimensionality.
101
102 texCubeEnables[i] = gles1State.isTextureTargetEnabled(i, TextureType::CubeMap);
103 tex2DEnables[i] =
104 !texCubeEnables[i] && (gles1State.isTextureTargetEnabled(i, TextureType::_2D));
105
106 Texture *curr2DTexture = glState->getSamplerTexture(i, TextureType::_2D);
107 if (curr2DTexture)
108 {
109 tex2DFormats[i] = gl::GetUnsizedFormat(
110 curr2DTexture->getFormat(TextureTarget::_2D, 0).info->internalFormat);
111 }
112 }
113
114 GLES1ShaderState::IntTexArray &texEnvModes = mShaderState.texEnvModes;
115 GLES1ShaderState::IntTexArray &texCombineRgbs = mShaderState.texCombineRgbs;
116 GLES1ShaderState::IntTexArray &texCombineAlphas = mShaderState.texCombineAlphas;
117 GLES1ShaderState::IntTexArray &texCombineSrc0Rgbs = mShaderState.texCombineSrc0Rgbs;
118 GLES1ShaderState::IntTexArray &texCombineSrc0Alphas = mShaderState.texCombineSrc0Alphas;
119 GLES1ShaderState::IntTexArray &texCombineSrc1Rgbs = mShaderState.texCombineSrc1Rgbs;
120 GLES1ShaderState::IntTexArray &texCombineSrc1Alphas = mShaderState.texCombineSrc1Alphas;
121 GLES1ShaderState::IntTexArray &texCombineSrc2Rgbs = mShaderState.texCombineSrc2Rgbs;
122 GLES1ShaderState::IntTexArray &texCombineSrc2Alphas = mShaderState.texCombineSrc2Alphas;
123 GLES1ShaderState::IntTexArray &texCombineOp0Rgbs = mShaderState.texCombineOp0Rgbs;
124 GLES1ShaderState::IntTexArray &texCombineOp0Alphas = mShaderState.texCombineOp0Alphas;
125 GLES1ShaderState::IntTexArray &texCombineOp1Rgbs = mShaderState.texCombineOp1Rgbs;
126 GLES1ShaderState::IntTexArray &texCombineOp1Alphas = mShaderState.texCombineOp1Alphas;
127 GLES1ShaderState::IntTexArray &texCombineOp2Rgbs = mShaderState.texCombineOp2Rgbs;
128 GLES1ShaderState::IntTexArray &texCombineOp2Alphas = mShaderState.texCombineOp2Alphas;
129
130 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_TEXTURE_ENVIRONMENT))
131 {
132 for (int i = 0; i < kTexUnitCount; i++)
133 {
134 const auto &env = gles1State.textureEnvironment(i);
135 texEnvModes[i] = ToGLenum(env.mode);
136 texCombineRgbs[i] = ToGLenum(env.combineRgb);
137 texCombineAlphas[i] = ToGLenum(env.combineAlpha);
138 texCombineSrc0Rgbs[i] = ToGLenum(env.src0Rgb);
139 texCombineSrc0Alphas[i] = ToGLenum(env.src0Alpha);
140 texCombineSrc1Rgbs[i] = ToGLenum(env.src1Rgb);
141 texCombineSrc1Alphas[i] = ToGLenum(env.src1Alpha);
142 texCombineSrc2Rgbs[i] = ToGLenum(env.src2Rgb);
143 texCombineSrc2Alphas[i] = ToGLenum(env.src2Alpha);
144 texCombineOp0Rgbs[i] = ToGLenum(env.op0Rgb);
145 texCombineOp0Alphas[i] = ToGLenum(env.op0Alpha);
146 texCombineOp1Rgbs[i] = ToGLenum(env.op1Rgb);
147 texCombineOp1Alphas[i] = ToGLenum(env.op1Alpha);
148 texCombineOp2Rgbs[i] = ToGLenum(env.op2Rgb);
149 texCombineOp2Alphas[i] = ToGLenum(env.op2Alpha);
150 }
151 }
152
153 bool enableClipPlanes = false;
154 GLES1ShaderState::BoolClipPlaneArray &clipPlaneEnables = mShaderState.clipPlaneEnables;
155 for (int i = 0; i < kClipPlaneCount; i++)
156 {
157 clipPlaneEnables[i] = glState->getEnableFeature(GL_CLIP_PLANE0 + i);
158 enableClipPlanes = enableClipPlanes || clipPlaneEnables[i];
159 }
160
161 mShaderState.mGLES1StateEnabled[GLES1StateEnables::ClipPlanes] = enableClipPlanes;
162 mShaderState.mGLES1StateEnabled[GLES1StateEnables::DrawTexture] = mDrawTextureEnabled;
163 mShaderState.mGLES1StateEnabled[GLES1StateEnables::PointRasterization] =
164 mode == PrimitiveMode::Points;
165 mShaderState.mGLES1StateEnabled[GLES1StateEnables::ShadeModelFlat] =
166 gles1State.mShadeModel == ShadingModel::Flat;
167 mShaderState.mGLES1StateEnabled[GLES1StateEnables::AlphaTest] =
168 glState->getEnableFeature(GL_ALPHA_TEST);
169 mShaderState.mGLES1StateEnabled[GLES1StateEnables::Lighting] =
170 glState->getEnableFeature(GL_LIGHTING);
171 mShaderState.mGLES1StateEnabled[GLES1StateEnables::RescaleNormal] =
172 glState->getEnableFeature(GL_RESCALE_NORMAL);
173 mShaderState.mGLES1StateEnabled[GLES1StateEnables::Normalize] =
174 glState->getEnableFeature(GL_NORMALIZE);
175 mShaderState.mGLES1StateEnabled[GLES1StateEnables::Fog] = glState->getEnableFeature(GL_FOG);
176 mShaderState.mGLES1StateEnabled[GLES1StateEnables::PointSprite] =
177 glState->getEnableFeature(GL_POINT_SPRITE_OES);
178 mShaderState.mGLES1StateEnabled[GLES1StateEnables::ColorMaterial] =
179 glState->getEnableFeature(GL_COLOR_MATERIAL);
180
181 // TODO (lfy@google.com): Implement two-sided lighting model (lightModel.twoSided)
182 mShaderState.mGLES1StateEnabled[GLES1StateEnables::LightModelTwoSided] = false;
183
184 GLES1ShaderState::BoolTexArray &pointSpriteCoordReplaces =
185 mShaderState.pointSpriteCoordReplaces;
186 for (int i = 0; i < kTexUnitCount; i++)
187 {
188 const auto &env = gles1State.textureEnvironment(i);
189 pointSpriteCoordReplaces[i] = env.pointSpriteCoordReplace;
190 }
191
192 GLES1ShaderState::BoolLightArray &lightEnables = mShaderState.lightEnables;
193 for (int i = 0; i < kLightCount; i++)
194 {
195 const auto &light = gles1State.mLights[i];
196 lightEnables[i] = light.enabled;
197 }
198
199 mShaderState.alphaTestFunc = gles1State.mAlphaTestFunc;
200 mShaderState.fogMode = gles1State.fogParameters().mode;
201
202 // All the states set before this spot affect ubershader creation
203
204 ANGLE_TRY(initializeRendererProgram(context, glState));
205
206 GLES1UberShaderState UberShaderState = getUberShaderState();
207
208 const GLES1ProgramState &programState = UberShaderState.programState;
209 GLES1UniformBuffers &uniformBuffers = UberShaderState.uniformBuffers;
210
211 Program *programObject = getProgram(programState.program);
212
213 // If anything is dirty in gles1 or the common parts of gles1/2, just redo these parts
214 // completely for now.
215
216 // Feature enables
217
218 // Texture unit enables and format info
219 std::array<Vec4Uniform, kTexUnitCount> texCropRects;
220 Vec4Uniform *cropRectBuffer = texCropRects.data();
221 for (int i = 0; i < kTexUnitCount; i++)
222 {
223 Texture *curr2DTexture = glState->getSamplerTexture(i, TextureType::_2D);
224 if (curr2DTexture)
225 {
226 const gl::Rectangle &cropRect = curr2DTexture->getCrop();
227
228 GLfloat textureWidth =
229 static_cast<GLfloat>(curr2DTexture->getWidth(TextureTarget::_2D, 0));
230 GLfloat textureHeight =
231 static_cast<GLfloat>(curr2DTexture->getHeight(TextureTarget::_2D, 0));
232
233 if (textureWidth > 0.0f && textureHeight > 0.0f)
234 {
235 cropRectBuffer[i][0] = cropRect.x / textureWidth;
236 cropRectBuffer[i][1] = cropRect.y / textureHeight;
237 cropRectBuffer[i][2] = cropRect.width / textureWidth;
238 cropRectBuffer[i][3] = cropRect.height / textureHeight;
239 }
240 }
241 }
242 setUniform4fv(programObject, programState.drawTextureNormalizedCropRectLoc, kTexUnitCount,
243 reinterpret_cast<GLfloat *>(cropRectBuffer));
244
245 // Client state / current vector enables
246 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_CLIENT_STATE_ENABLE) ||
247 gles1State.isDirty(GLES1State::DIRTY_GLES1_CURRENT_VECTOR))
248 {
249 if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Normal))
250 {
251 const angle::Vector3 normal = gles1State.getCurrentNormal();
252 context->vertexAttrib3f(kNormalAttribIndex, normal.x(), normal.y(), normal.z());
253 }
254
255 if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Color))
256 {
257 const ColorF color = gles1State.getCurrentColor();
258 context->vertexAttrib4f(kColorAttribIndex, color.red, color.green, color.blue,
259 color.alpha);
260 }
261
262 if (!gles1State.isClientStateEnabled(ClientVertexArrayType::PointSize))
263 {
264 GLfloat pointSize = gles1State.mPointParameters.pointSize;
265 context->vertexAttrib1f(kPointSizeAttribIndex, pointSize);
266 }
267
268 for (int i = 0; i < kTexUnitCount; i++)
269 {
270 if (!gles1State.mTexCoordArrayEnabled[i])
271 {
272 const TextureCoordF texcoord = gles1State.getCurrentTextureCoords(i);
273 context->vertexAttrib4f(kTextureCoordAttribIndexBase + i, texcoord.s, texcoord.t,
274 texcoord.r, texcoord.q);
275 }
276 }
277 }
278
279 // Matrices
280 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_MATRICES))
281 {
282 angle::Mat4 proj = gles1State.mProjectionMatrices.back();
283 setUniformMatrix4fv(programObject, programState.projMatrixLoc, 1, GL_FALSE, proj.data());
284
285 angle::Mat4 modelview = gles1State.mModelviewMatrices.back();
286 setUniformMatrix4fv(programObject, programState.modelviewMatrixLoc, 1, GL_FALSE,
287 modelview.data());
288
289 angle::Mat4 modelviewInvTr = modelview.transpose().inverse();
290 setUniformMatrix4fv(programObject, programState.modelviewInvTrLoc, 1, GL_FALSE,
291 modelviewInvTr.data());
292
293 Mat4Uniform *textureMatrixBuffer = uniformBuffers.textureMatrices.data();
294
295 for (int i = 0; i < kTexUnitCount; i++)
296 {
297 angle::Mat4 textureMatrix = gles1State.mTextureMatrices[i].back();
298 memcpy(textureMatrixBuffer + i, textureMatrix.data(), sizeof(Mat4Uniform));
299 }
300
301 setUniformMatrix4fv(programObject, programState.textureMatrixLoc, kTexUnitCount, GL_FALSE,
302 reinterpret_cast<float *>(uniformBuffers.textureMatrices.data()));
303 }
304
305 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_TEXTURE_ENVIRONMENT))
306 {
307 for (int i = 0; i < kTexUnitCount; i++)
308 {
309 const auto &env = gles1State.textureEnvironment(i);
310
311 uniformBuffers.texEnvColors[i][0] = env.color.red;
312 uniformBuffers.texEnvColors[i][1] = env.color.green;
313 uniformBuffers.texEnvColors[i][2] = env.color.blue;
314 uniformBuffers.texEnvColors[i][3] = env.color.alpha;
315
316 uniformBuffers.texEnvRgbScales[i] = env.rgbScale;
317 uniformBuffers.texEnvAlphaScales[i] = env.alphaScale;
318 }
319
320 setUniform4fv(programObject, programState.textureEnvColorLoc, kTexUnitCount,
321 reinterpret_cast<float *>(uniformBuffers.texEnvColors.data()));
322 setUniform1fv(programObject, programState.rgbScaleLoc, kTexUnitCount,
323 uniformBuffers.texEnvRgbScales.data());
324 setUniform1fv(programObject, programState.alphaScaleLoc, kTexUnitCount,
325 uniformBuffers.texEnvAlphaScales.data());
326 }
327
328 // Alpha test
329 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_ALPHA_TEST))
330 {
331 setUniform1f(programObject, programState.alphaTestRefLoc, gles1State.mAlphaTestRef);
332 }
333
334 // Shading, materials, and lighting
335 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_MATERIAL))
336 {
337 const auto &material = gles1State.mMaterial;
338
339 setUniform4fv(programObject, programState.materialAmbientLoc, 1, material.ambient.data());
340 setUniform4fv(programObject, programState.materialDiffuseLoc, 1, material.diffuse.data());
341 setUniform4fv(programObject, programState.materialSpecularLoc, 1, material.specular.data());
342 setUniform4fv(programObject, programState.materialEmissiveLoc, 1, material.emissive.data());
343 setUniform1f(programObject, programState.materialSpecularExponentLoc,
344 material.specularExponent);
345 }
346
347 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LIGHTS))
348 {
349 const auto &lightModel = gles1State.mLightModel;
350
351 setUniform4fv(programObject, programState.lightModelSceneAmbientLoc, 1,
352 lightModel.color.data());
353
354 for (int i = 0; i < kLightCount; i++)
355 {
356 const auto &light = gles1State.mLights[i];
357 memcpy(uniformBuffers.lightAmbients.data() + i, light.ambient.data(),
358 sizeof(Vec4Uniform));
359 memcpy(uniformBuffers.lightDiffuses.data() + i, light.diffuse.data(),
360 sizeof(Vec4Uniform));
361 memcpy(uniformBuffers.lightSpeculars.data() + i, light.specular.data(),
362 sizeof(Vec4Uniform));
363 memcpy(uniformBuffers.lightPositions.data() + i, light.position.data(),
364 sizeof(Vec4Uniform));
365 memcpy(uniformBuffers.lightDirections.data() + i, light.direction.data(),
366 sizeof(Vec3Uniform));
367 uniformBuffers.spotlightExponents[i] = light.spotlightExponent;
368 uniformBuffers.spotlightCutoffAngles[i] = light.spotlightCutoffAngle;
369 uniformBuffers.attenuationConsts[i] = light.attenuationConst;
370 uniformBuffers.attenuationLinears[i] = light.attenuationLinear;
371 uniformBuffers.attenuationQuadratics[i] = light.attenuationQuadratic;
372 }
373
374 setUniform4fv(programObject, programState.lightAmbientsLoc, kLightCount,
375 reinterpret_cast<float *>(uniformBuffers.lightAmbients.data()));
376 setUniform4fv(programObject, programState.lightDiffusesLoc, kLightCount,
377 reinterpret_cast<float *>(uniformBuffers.lightDiffuses.data()));
378 setUniform4fv(programObject, programState.lightSpecularsLoc, kLightCount,
379 reinterpret_cast<float *>(uniformBuffers.lightSpeculars.data()));
380 setUniform4fv(programObject, programState.lightPositionsLoc, kLightCount,
381 reinterpret_cast<float *>(uniformBuffers.lightPositions.data()));
382 setUniform3fv(programObject, programState.lightDirectionsLoc, kLightCount,
383 reinterpret_cast<float *>(uniformBuffers.lightDirections.data()));
384 setUniform1fv(programObject, programState.lightSpotlightExponentsLoc, kLightCount,
385 reinterpret_cast<float *>(uniformBuffers.spotlightExponents.data()));
386 setUniform1fv(programObject, programState.lightSpotlightCutoffAnglesLoc, kLightCount,
387 reinterpret_cast<float *>(uniformBuffers.spotlightCutoffAngles.data()));
388 setUniform1fv(programObject, programState.lightAttenuationConstsLoc, kLightCount,
389 reinterpret_cast<float *>(uniformBuffers.attenuationConsts.data()));
390 setUniform1fv(programObject, programState.lightAttenuationLinearsLoc, kLightCount,
391 reinterpret_cast<float *>(uniformBuffers.attenuationLinears.data()));
392 setUniform1fv(programObject, programState.lightAttenuationQuadraticsLoc, kLightCount,
393 reinterpret_cast<float *>(uniformBuffers.attenuationQuadratics.data()));
394 }
395
396 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_FOG))
397 {
398 const FogParameters &fog = gles1State.fogParameters();
399 setUniform1f(programObject, programState.fogDensityLoc, fog.density);
400 setUniform1f(programObject, programState.fogStartLoc, fog.start);
401 setUniform1f(programObject, programState.fogEndLoc, fog.end);
402 setUniform4fv(programObject, programState.fogColorLoc, 1, fog.color.data());
403 }
404
405 // Clip planes
406 if (gles1State.isDirty(GLES1State::DIRTY_GLES1_CLIP_PLANES))
407 {
408 for (int i = 0; i < kClipPlaneCount; i++)
409 {
410 gles1State.getClipPlane(
411 i, reinterpret_cast<float *>(uniformBuffers.clipPlanes.data() + i));
412 }
413
414 setUniform4fv(programObject, programState.clipPlanesLoc, kClipPlaneCount,
415 reinterpret_cast<float *>(uniformBuffers.clipPlanes.data()));
416 }
417
418 // Point rasterization
419 {
420 const PointParameters &pointParams = gles1State.mPointParameters;
421
422 setUniform1f(programObject, programState.pointSizeMinLoc, pointParams.pointSizeMin);
423 setUniform1f(programObject, programState.pointSizeMaxLoc, pointParams.pointSizeMax);
424 setUniform3fv(programObject, programState.pointDistanceAttenuationLoc, 1,
425 pointParams.pointDistanceAttenuation.data());
426 }
427
428 // Draw texture
429 {
430 setUniform4fv(programObject, programState.drawTextureCoordsLoc, 1, mDrawTextureCoords);
431 setUniform2fv(programObject, programState.drawTextureDimsLoc, 1, mDrawTextureDims);
432 }
433
434 gles1State.clearDirty();
435
436 // None of those are changes in sampler, so there is no need to set the GL_PROGRAM dirty.
437 // Otherwise, put the dirtying here.
438
439 return angle::Result::Continue;
440 }
441
442 // static
VertexArrayIndex(ClientVertexArrayType type,const GLES1State & gles1)443 int GLES1Renderer::VertexArrayIndex(ClientVertexArrayType type, const GLES1State &gles1)
444 {
445 switch (type)
446 {
447 case ClientVertexArrayType::Vertex:
448 return kVertexAttribIndex;
449 case ClientVertexArrayType::Normal:
450 return kNormalAttribIndex;
451 case ClientVertexArrayType::Color:
452 return kColorAttribIndex;
453 case ClientVertexArrayType::PointSize:
454 return kPointSizeAttribIndex;
455 case ClientVertexArrayType::TextureCoord:
456 return kTextureCoordAttribIndexBase + gles1.getClientTextureUnit();
457 default:
458 UNREACHABLE();
459 return 0;
460 }
461 }
462
463 // static
VertexArrayType(int attribIndex)464 ClientVertexArrayType GLES1Renderer::VertexArrayType(int attribIndex)
465 {
466 switch (attribIndex)
467 {
468 case kVertexAttribIndex:
469 return ClientVertexArrayType::Vertex;
470 case kNormalAttribIndex:
471 return ClientVertexArrayType::Normal;
472 case kColorAttribIndex:
473 return ClientVertexArrayType::Color;
474 case kPointSizeAttribIndex:
475 return ClientVertexArrayType::PointSize;
476 default:
477 if (attribIndex < kTextureCoordAttribIndexBase + kTexUnitCount)
478 {
479 return ClientVertexArrayType::TextureCoord;
480 }
481 UNREACHABLE();
482 return ClientVertexArrayType::InvalidEnum;
483 }
484 }
485
486 // static
TexCoordArrayIndex(unsigned int unit)487 int GLES1Renderer::TexCoordArrayIndex(unsigned int unit)
488 {
489 return kTextureCoordAttribIndexBase + unit;
490 }
491
drawTexture(Context * context,State * glState,float x,float y,float z,float width,float height)492 void GLES1Renderer::drawTexture(Context *context,
493 State *glState,
494 float x,
495 float y,
496 float z,
497 float width,
498 float height)
499 {
500
501 // get viewport
502 const gl::Rectangle &viewport = glState->getViewport();
503
504 // Translate from viewport to NDC for feeding the shader.
505 // Recenter, rescale. (e.g., [0, 0, 1080, 1920] -> [-1, -1, 1, 1])
506 float xNdc = scaleScreenCoordinateToNdc(x, static_cast<GLfloat>(viewport.width));
507 float yNdc = scaleScreenCoordinateToNdc(y, static_cast<GLfloat>(viewport.height));
508 float wNdc = scaleScreenDimensionToNdc(width, static_cast<GLfloat>(viewport.width));
509 float hNdc = scaleScreenDimensionToNdc(height, static_cast<GLfloat>(viewport.height));
510
511 float zNdc = 2.0f * clamp(z, 0.0f, 1.0f) - 1.0f;
512
513 mDrawTextureCoords[0] = xNdc;
514 mDrawTextureCoords[1] = yNdc;
515 mDrawTextureCoords[2] = zNdc;
516
517 mDrawTextureDims[0] = wNdc;
518 mDrawTextureDims[1] = hNdc;
519
520 mDrawTextureEnabled = true;
521
522 AttributesMask prevAttributesMask = glState->gles1().getVertexArraysAttributeMask();
523
524 setAttributesEnabled(context, glState, AttributesMask());
525
526 glState->gles1().setAllDirty();
527
528 context->drawArrays(PrimitiveMode::Triangles, 0, 6);
529
530 setAttributesEnabled(context, glState, prevAttributesMask);
531
532 mDrawTextureEnabled = false;
533 }
534
getShader(ShaderProgramID handle) const535 Shader *GLES1Renderer::getShader(ShaderProgramID handle) const
536 {
537 return mShaderPrograms->getShader(handle);
538 }
539
getProgram(ShaderProgramID handle) const540 Program *GLES1Renderer::getProgram(ShaderProgramID handle) const
541 {
542 return mShaderPrograms->getProgram(handle);
543 }
544
compileShader(Context * context,ShaderType shaderType,const char * src,ShaderProgramID * shaderOut)545 angle::Result GLES1Renderer::compileShader(Context *context,
546 ShaderType shaderType,
547 const char *src,
548 ShaderProgramID *shaderOut)
549 {
550 rx::ContextImpl *implementation = context->getImplementation();
551 const Limitations &limitations = implementation->getNativeLimitations();
552
553 ShaderProgramID shader = mShaderPrograms->createShader(implementation, limitations, shaderType);
554
555 Shader *shaderObject = getShader(shader);
556 ANGLE_CHECK(context, shaderObject, "Missing shader object", GL_INVALID_OPERATION);
557
558 shaderObject->setSource(1, &src, nullptr);
559 shaderObject->compile(context);
560
561 *shaderOut = shader;
562
563 if (!shaderObject->isCompiled())
564 {
565 GLint infoLogLength = shaderObject->getInfoLogLength();
566 std::vector<char> infoLog(infoLogLength, 0);
567 shaderObject->getInfoLog(infoLogLength - 1, nullptr, infoLog.data());
568
569 ERR() << "Internal GLES 1 shader compile failed. Info log: " << infoLog.data();
570 ANGLE_CHECK(context, false, "GLES1Renderer shader compile failed.", GL_INVALID_OPERATION);
571 return angle::Result::Stop;
572 }
573
574 return angle::Result::Continue;
575 }
576
linkProgram(Context * context,State * glState,ShaderProgramID vertexShader,ShaderProgramID fragmentShader,const angle::HashMap<GLint,std::string> & attribLocs,ShaderProgramID * programOut)577 angle::Result GLES1Renderer::linkProgram(Context *context,
578 State *glState,
579 ShaderProgramID vertexShader,
580 ShaderProgramID fragmentShader,
581 const angle::HashMap<GLint, std::string> &attribLocs,
582 ShaderProgramID *programOut)
583 {
584 ShaderProgramID program = mShaderPrograms->createProgram(context->getImplementation());
585
586 Program *programObject = getProgram(program);
587 ANGLE_CHECK(context, programObject, "Missing program object", GL_INVALID_OPERATION);
588
589 *programOut = program;
590
591 programObject->attachShader(getShader(vertexShader));
592 programObject->attachShader(getShader(fragmentShader));
593
594 for (auto it : attribLocs)
595 {
596 GLint index = it.first;
597 const std::string &name = it.second;
598 programObject->bindAttributeLocation(index, name.c_str());
599 }
600
601 ANGLE_TRY(programObject->link(context));
602 programObject->resolveLink(context);
603
604 ANGLE_TRY(glState->onProgramExecutableChange(context, programObject));
605
606 if (!programObject->isLinked())
607 {
608 GLint infoLogLength = programObject->getExecutable().getInfoLogLength();
609 std::vector<char> infoLog(infoLogLength, 0);
610 programObject->getExecutable().getInfoLog(infoLogLength - 1, nullptr, infoLog.data());
611
612 ERR() << "Internal GLES 1 shader link failed. Info log: " << infoLog.data();
613 ANGLE_CHECK(context, false, "GLES1Renderer program link failed.", GL_INVALID_OPERATION);
614 return angle::Result::Stop;
615 }
616
617 programObject->detachShader(context, getShader(vertexShader));
618 programObject->detachShader(context, getShader(fragmentShader));
619
620 return angle::Result::Continue;
621 }
622
getShaderBool(GLES1StateEnables state)623 const char *GLES1Renderer::getShaderBool(GLES1StateEnables state)
624 {
625 if (mShaderState.mGLES1StateEnabled[state])
626 {
627 return "true";
628 }
629 else
630 {
631 return "false";
632 }
633 }
634
addShaderDefine(std::stringstream & outStream,GLES1StateEnables state,const char * enableString)635 void GLES1Renderer::addShaderDefine(std::stringstream &outStream,
636 GLES1StateEnables state,
637 const char *enableString)
638 {
639 outStream << "\n";
640 outStream << "#define " << enableString << " " << getShaderBool(state);
641 }
642
addShaderInt(std::stringstream & outStream,const char * name,int value)643 void GLES1Renderer::addShaderInt(std::stringstream &outStream, const char *name, int value)
644 {
645 outStream << "\n";
646 outStream << "const int " << name << " = " << value << ";";
647 }
648
addShaderIntTexArray(std::stringstream & outStream,const char * texString,GLES1ShaderState::IntTexArray & texState)649 void GLES1Renderer::addShaderIntTexArray(std::stringstream &outStream,
650 const char *texString,
651 GLES1ShaderState::IntTexArray &texState)
652 {
653 outStream << "\n";
654 outStream << "const int " << texString << "[kMaxTexUnits] = int[kMaxTexUnits](";
655 for (int i = 0; i < kTexUnitCount; i++)
656 {
657 if (i != 0)
658 {
659 outStream << ", ";
660 }
661 outStream << texState[i];
662 }
663 outStream << ");";
664 }
665
addShaderBoolTexArray(std::stringstream & outStream,const char * name,GLES1ShaderState::BoolTexArray & value)666 void GLES1Renderer::addShaderBoolTexArray(std::stringstream &outStream,
667 const char *name,
668 GLES1ShaderState::BoolTexArray &value)
669 {
670 outStream << std::boolalpha;
671 outStream << "\n";
672 outStream << "bool " << name << "[kMaxTexUnits] = bool[kMaxTexUnits](";
673 for (int i = 0; i < kTexUnitCount; i++)
674 {
675 if (i != 0)
676 {
677 outStream << ", ";
678 }
679 outStream << value[i];
680 }
681 outStream << ");";
682 }
683
addShaderBoolLightArray(std::stringstream & outStream,const char * name,GLES1ShaderState::BoolLightArray & value)684 void GLES1Renderer::addShaderBoolLightArray(std::stringstream &outStream,
685 const char *name,
686 GLES1ShaderState::BoolLightArray &value)
687 {
688 outStream << std::boolalpha;
689 outStream << "\n";
690 outStream << "bool " << name << "[kMaxLights] = bool[kMaxLights](";
691 for (int i = 0; i < kLightCount; i++)
692 {
693 if (i != 0)
694 {
695 outStream << ", ";
696 }
697 outStream << value[i];
698 }
699 outStream << ");";
700 }
701
addShaderBoolClipPlaneArray(std::stringstream & outStream,const char * name,GLES1ShaderState::BoolClipPlaneArray & value)702 void GLES1Renderer::addShaderBoolClipPlaneArray(std::stringstream &outStream,
703 const char *name,
704 GLES1ShaderState::BoolClipPlaneArray &value)
705 {
706 outStream << std::boolalpha;
707 outStream << "\n";
708 outStream << "bool " << name << "[kMaxClipPlanes] = bool[kMaxClipPlanes](";
709 for (int i = 0; i < kClipPlaneCount; i++)
710 {
711 if (i != 0)
712 {
713 outStream << ", ";
714 }
715 outStream << value[i];
716 }
717 outStream << ");";
718 }
719
addVertexShaderDefs(std::stringstream & outStream)720 void GLES1Renderer::addVertexShaderDefs(std::stringstream &outStream)
721 {
722 addShaderDefine(outStream, GLES1StateEnables::DrawTexture, "enable_draw_texture");
723 addShaderDefine(outStream, GLES1StateEnables::PointRasterization, "point_rasterization");
724 addShaderDefine(outStream, GLES1StateEnables::RescaleNormal, "enable_rescale_normal");
725 addShaderDefine(outStream, GLES1StateEnables::Normalize, "enable_normalize");
726 }
727
addFragmentShaderDefs(std::stringstream & outStream)728 void GLES1Renderer::addFragmentShaderDefs(std::stringstream &outStream)
729 {
730 addShaderDefine(outStream, GLES1StateEnables::Lighting, "enable_lighting");
731 addShaderDefine(outStream, GLES1StateEnables::Fog, "enable_fog");
732 addShaderDefine(outStream, GLES1StateEnables::ClipPlanes, "enable_clip_planes");
733 addShaderDefine(outStream, GLES1StateEnables::DrawTexture, "enable_draw_texture");
734 addShaderDefine(outStream, GLES1StateEnables::PointRasterization, "point_rasterization");
735 addShaderDefine(outStream, GLES1StateEnables::PointSprite, "point_sprite_enabled");
736 addShaderDefine(outStream, GLES1StateEnables::AlphaTest, "enable_alpha_test");
737 addShaderDefine(outStream, GLES1StateEnables::ShadeModelFlat, "shade_model_flat");
738 addShaderDefine(outStream, GLES1StateEnables::ColorMaterial, "enable_color_material");
739 addShaderDefine(outStream, GLES1StateEnables::LightModelTwoSided, "light_model_two_sided");
740
741 // bool enable_texture_2d[kMaxTexUnits] = bool[kMaxTexUnits](...);
742 addShaderBoolTexArray(outStream, "enable_texture_2d", mShaderState.tex2DEnables);
743
744 // bool enable_texture_cube_map[kMaxTexUnits] = bool[kMaxTexUnits](...);
745 addShaderBoolTexArray(outStream, "enable_texture_cube_map", mShaderState.texCubeEnables);
746
747 // int texture_format[kMaxTexUnits] = int[kMaxTexUnits](...);
748 addShaderIntTexArray(outStream, "texture_format", mShaderState.tex2DFormats);
749
750 // bool point_sprite_coord_replace[kMaxTexUnits] = bool[kMaxTexUnits](...);
751 addShaderBoolTexArray(outStream, "point_sprite_coord_replace",
752 mShaderState.pointSpriteCoordReplaces);
753
754 // bool light_enables[kMaxLights] = bool[kMaxLights](...);
755 addShaderBoolLightArray(outStream, "light_enables", mShaderState.lightEnables);
756
757 // bool clip_plane_enables[kMaxClipPlanes] = bool[kMaxClipPlanes](...);
758 addShaderBoolClipPlaneArray(outStream, "clip_plane_enables", mShaderState.clipPlaneEnables);
759
760 // int texture_format[kMaxTexUnits] = int[kMaxTexUnits](...);
761 addShaderIntTexArray(outStream, "texture_env_mode", mShaderState.texEnvModes);
762
763 // int combine_rgb[kMaxTexUnits];
764 addShaderIntTexArray(outStream, "combine_rgb", mShaderState.texCombineRgbs);
765
766 // int combine_alpha[kMaxTexUnits];
767 addShaderIntTexArray(outStream, "combine_alpha", mShaderState.texCombineAlphas);
768
769 // int src0_rgb[kMaxTexUnits];
770 addShaderIntTexArray(outStream, "src0_rgb", mShaderState.texCombineSrc0Rgbs);
771
772 // int src0_alpha[kMaxTexUnits];
773 addShaderIntTexArray(outStream, "src0_alpha", mShaderState.texCombineSrc0Alphas);
774
775 // int src1_rgb[kMaxTexUnits];
776 addShaderIntTexArray(outStream, "src1_rgb", mShaderState.texCombineSrc1Rgbs);
777
778 // int src1_alpha[kMaxTexUnits];
779 addShaderIntTexArray(outStream, "src1_alpha", mShaderState.texCombineSrc1Alphas);
780
781 // int src2_rgb[kMaxTexUnits];
782 addShaderIntTexArray(outStream, "src2_rgb", mShaderState.texCombineSrc2Rgbs);
783
784 // int src2_alpha[kMaxTexUnits];
785 addShaderIntTexArray(outStream, "src2_alpha", mShaderState.texCombineSrc2Alphas);
786
787 // int op0_rgb[kMaxTexUnits];
788 addShaderIntTexArray(outStream, "op0_rgb", mShaderState.texCombineOp0Rgbs);
789
790 // int op0_alpha[kMaxTexUnits];
791 addShaderIntTexArray(outStream, "op0_alpha", mShaderState.texCombineOp0Alphas);
792
793 // int op1_rgb[kMaxTexUnits];
794 addShaderIntTexArray(outStream, "op1_rgb", mShaderState.texCombineOp1Rgbs);
795
796 // int op1_alpha[kMaxTexUnits];
797 addShaderIntTexArray(outStream, "op1_alpha", mShaderState.texCombineOp1Alphas);
798
799 // int op2_rgb[kMaxTexUnits];
800 addShaderIntTexArray(outStream, "op2_rgb", mShaderState.texCombineOp2Rgbs);
801
802 // int op2_alpha[kMaxTexUnits];
803 addShaderIntTexArray(outStream, "op2_alpha", mShaderState.texCombineOp2Alphas);
804
805 // int alpha_func;
806 addShaderInt(outStream, "alpha_func", ToGLenum(mShaderState.alphaTestFunc));
807
808 // int fog_mode;
809 addShaderInt(outStream, "fog_mode", ToGLenum(mShaderState.fogMode));
810 }
811
initializeRendererProgram(Context * context,State * glState)812 angle::Result GLES1Renderer::initializeRendererProgram(Context *context, State *glState)
813 {
814 // See if we have the shader for this combination of states
815 if (mUberShaderState.find(mShaderState) != mUberShaderState.end())
816 {
817 Program *programObject = getProgram(getUberShaderState().programState.program);
818
819 // If this is different than the current program, we need to sync everything
820 // TODO: This could be optimized to only dirty state that differs between the two programs
821 if (glState->getProgram()->id() != programObject->id())
822 {
823 glState->gles1().setAllDirty();
824 }
825
826 ANGLE_TRY(glState->setProgram(context, programObject));
827 return angle::Result::Continue;
828 }
829
830 if (!mRendererProgramInitialized)
831 {
832 mShaderPrograms = new ShaderProgramManager();
833 }
834
835 // If we get here, we don't have a shader for this state, need to create it
836 GLES1ProgramState &programState = mUberShaderState[mShaderState].programState;
837
838 ShaderProgramID vertexShader;
839 ShaderProgramID fragmentShader;
840
841 std::stringstream GLES1DrawVShaderStateDefs;
842 addVertexShaderDefs(GLES1DrawVShaderStateDefs);
843
844 std::stringstream vertexStream;
845 vertexStream << kGLES1DrawVShaderHeader;
846 vertexStream << GLES1DrawVShaderStateDefs.str();
847 vertexStream << kGLES1DrawVShader;
848
849 ANGLE_TRY(
850 compileShader(context, ShaderType::Vertex, vertexStream.str().c_str(), &vertexShader));
851
852 std::stringstream GLES1DrawFShaderStateDefs;
853 addFragmentShaderDefs(GLES1DrawFShaderStateDefs);
854
855 std::stringstream fragmentStream;
856 fragmentStream << kGLES1DrawFShaderHeader;
857 fragmentStream << GLES1DrawFShaderStateDefs.str();
858 fragmentStream << kGLES1DrawFShaderUniformDefs;
859 fragmentStream << kGLES1DrawFShaderFunctions;
860 fragmentStream << kGLES1DrawFShaderMultitexturing;
861 fragmentStream << kGLES1DrawFShaderMain;
862
863 ANGLE_TRY(compileShader(context, ShaderType::Fragment, fragmentStream.str().c_str(),
864 &fragmentShader));
865
866 angle::HashMap<GLint, std::string> attribLocs;
867
868 attribLocs[(GLint)kVertexAttribIndex] = "pos";
869 attribLocs[(GLint)kNormalAttribIndex] = "normal";
870 attribLocs[(GLint)kColorAttribIndex] = "color";
871 attribLocs[(GLint)kPointSizeAttribIndex] = "pointsize";
872
873 for (int i = 0; i < kTexUnitCount; i++)
874 {
875 std::stringstream ss;
876 ss << "texcoord" << i;
877 attribLocs[kTextureCoordAttribIndexBase + i] = ss.str();
878 }
879
880 ANGLE_TRY(linkProgram(context, glState, vertexShader, fragmentShader, attribLocs,
881 &programState.program));
882
883 mShaderPrograms->deleteShader(context, vertexShader);
884 mShaderPrograms->deleteShader(context, fragmentShader);
885
886 Program *programObject = getProgram(programState.program);
887
888 programState.projMatrixLoc = programObject->getUniformLocation("projection");
889 programState.modelviewMatrixLoc = programObject->getUniformLocation("modelview");
890 programState.textureMatrixLoc = programObject->getUniformLocation("texture_matrix");
891 programState.modelviewInvTrLoc = programObject->getUniformLocation("modelview_invtr");
892
893 for (int i = 0; i < kTexUnitCount; i++)
894 {
895 std::stringstream ss2d;
896 std::stringstream sscube;
897
898 ss2d << "tex_sampler" << i;
899 sscube << "tex_cube_sampler" << i;
900
901 programState.tex2DSamplerLocs[i] = programObject->getUniformLocation(ss2d.str().c_str());
902 programState.texCubeSamplerLocs[i] =
903 programObject->getUniformLocation(sscube.str().c_str());
904 }
905
906 programState.textureEnvColorLoc = programObject->getUniformLocation("texture_env_color");
907 programState.rgbScaleLoc = programObject->getUniformLocation("texture_env_rgb_scale");
908 programState.alphaScaleLoc = programObject->getUniformLocation("texture_env_alpha_scale");
909
910 programState.alphaTestRefLoc = programObject->getUniformLocation("alpha_test_ref");
911
912 programState.materialAmbientLoc = programObject->getUniformLocation("material_ambient");
913 programState.materialDiffuseLoc = programObject->getUniformLocation("material_diffuse");
914 programState.materialSpecularLoc = programObject->getUniformLocation("material_specular");
915 programState.materialEmissiveLoc = programObject->getUniformLocation("material_emissive");
916 programState.materialSpecularExponentLoc =
917 programObject->getUniformLocation("material_specular_exponent");
918
919 programState.lightModelSceneAmbientLoc =
920 programObject->getUniformLocation("light_model_scene_ambient");
921
922 programState.lightAmbientsLoc = programObject->getUniformLocation("light_ambients");
923 programState.lightDiffusesLoc = programObject->getUniformLocation("light_diffuses");
924 programState.lightSpecularsLoc = programObject->getUniformLocation("light_speculars");
925 programState.lightPositionsLoc = programObject->getUniformLocation("light_positions");
926 programState.lightDirectionsLoc = programObject->getUniformLocation("light_directions");
927 programState.lightSpotlightExponentsLoc =
928 programObject->getUniformLocation("light_spotlight_exponents");
929 programState.lightSpotlightCutoffAnglesLoc =
930 programObject->getUniformLocation("light_spotlight_cutoff_angles");
931 programState.lightAttenuationConstsLoc =
932 programObject->getUniformLocation("light_attenuation_consts");
933 programState.lightAttenuationLinearsLoc =
934 programObject->getUniformLocation("light_attenuation_linears");
935 programState.lightAttenuationQuadraticsLoc =
936 programObject->getUniformLocation("light_attenuation_quadratics");
937
938 programState.fogDensityLoc = programObject->getUniformLocation("fog_density");
939 programState.fogStartLoc = programObject->getUniformLocation("fog_start");
940 programState.fogEndLoc = programObject->getUniformLocation("fog_end");
941 programState.fogColorLoc = programObject->getUniformLocation("fog_color");
942
943 programState.clipPlanesLoc = programObject->getUniformLocation("clip_planes");
944
945 programState.pointSizeMinLoc = programObject->getUniformLocation("point_size_min");
946 programState.pointSizeMaxLoc = programObject->getUniformLocation("point_size_max");
947 programState.pointDistanceAttenuationLoc =
948 programObject->getUniformLocation("point_distance_attenuation");
949
950 programState.drawTextureCoordsLoc = programObject->getUniformLocation("draw_texture_coords");
951 programState.drawTextureDimsLoc = programObject->getUniformLocation("draw_texture_dims");
952 programState.drawTextureNormalizedCropRectLoc =
953 programObject->getUniformLocation("draw_texture_normalized_crop_rect");
954
955 ANGLE_TRY(glState->setProgram(context, programObject));
956
957 for (int i = 0; i < kTexUnitCount; i++)
958 {
959 setUniform1i(context, programObject, programState.tex2DSamplerLocs[i], i);
960 setUniform1i(context, programObject, programState.texCubeSamplerLocs[i], i + kTexUnitCount);
961 }
962 glState->setObjectDirty(GL_PROGRAM);
963
964 // We just created a new program, we need to sync everything
965 glState->gles1().setAllDirty();
966
967 mRendererProgramInitialized = true;
968 return angle::Result::Continue;
969 }
970
setUniform1i(Context * context,Program * programObject,UniformLocation location,GLint value)971 void GLES1Renderer::setUniform1i(Context *context,
972 Program *programObject,
973 UniformLocation location,
974 GLint value)
975 {
976 if (location.value == -1)
977 return;
978 programObject->setUniform1iv(context, location, 1, &value);
979 }
980
setUniform1iv(Context * context,Program * programObject,UniformLocation location,GLint count,const GLint * value)981 void GLES1Renderer::setUniform1iv(Context *context,
982 Program *programObject,
983 UniformLocation location,
984 GLint count,
985 const GLint *value)
986 {
987 if (location.value == -1)
988 return;
989 programObject->setUniform1iv(context, location, count, value);
990 }
991
setUniformMatrix4fv(Program * programObject,UniformLocation location,GLint count,GLboolean transpose,const GLfloat * value)992 void GLES1Renderer::setUniformMatrix4fv(Program *programObject,
993 UniformLocation location,
994 GLint count,
995 GLboolean transpose,
996 const GLfloat *value)
997 {
998 if (location.value == -1)
999 return;
1000 programObject->setUniformMatrix4fv(location, count, transpose, value);
1001 }
1002
setUniform4fv(Program * programObject,UniformLocation location,GLint count,const GLfloat * value)1003 void GLES1Renderer::setUniform4fv(Program *programObject,
1004 UniformLocation location,
1005 GLint count,
1006 const GLfloat *value)
1007 {
1008 if (location.value == -1)
1009 return;
1010 programObject->setUniform4fv(location, count, value);
1011 }
1012
setUniform3fv(Program * programObject,UniformLocation location,GLint count,const GLfloat * value)1013 void GLES1Renderer::setUniform3fv(Program *programObject,
1014 UniformLocation location,
1015 GLint count,
1016 const GLfloat *value)
1017 {
1018 if (location.value == -1)
1019 return;
1020 programObject->setUniform3fv(location, count, value);
1021 }
1022
setUniform2fv(Program * programObject,UniformLocation location,GLint count,const GLfloat * value)1023 void GLES1Renderer::setUniform2fv(Program *programObject,
1024 UniformLocation location,
1025 GLint count,
1026 const GLfloat *value)
1027 {
1028 if (location.value == -1)
1029 return;
1030 programObject->setUniform2fv(location, count, value);
1031 }
1032
setUniform1f(Program * programObject,UniformLocation location,GLfloat value)1033 void GLES1Renderer::setUniform1f(Program *programObject, UniformLocation location, GLfloat value)
1034 {
1035 if (location.value == -1)
1036 return;
1037 programObject->setUniform1fv(location, 1, &value);
1038 }
1039
setUniform1fv(Program * programObject,UniformLocation location,GLint count,const GLfloat * value)1040 void GLES1Renderer::setUniform1fv(Program *programObject,
1041 UniformLocation location,
1042 GLint count,
1043 const GLfloat *value)
1044 {
1045 if (location.value == -1)
1046 return;
1047 programObject->setUniform1fv(location, count, value);
1048 }
1049
setAttributesEnabled(Context * context,State * glState,AttributesMask mask)1050 void GLES1Renderer::setAttributesEnabled(Context *context, State *glState, AttributesMask mask)
1051 {
1052 GLES1State &gles1 = glState->gles1();
1053
1054 ClientVertexArrayType nonTexcoordArrays[] = {
1055 ClientVertexArrayType::Vertex,
1056 ClientVertexArrayType::Normal,
1057 ClientVertexArrayType::Color,
1058 ClientVertexArrayType::PointSize,
1059 };
1060
1061 for (const ClientVertexArrayType attrib : nonTexcoordArrays)
1062 {
1063 int index = VertexArrayIndex(attrib, glState->gles1());
1064
1065 if (mask.test(index))
1066 {
1067 gles1.setClientStateEnabled(attrib, true);
1068 context->enableVertexAttribArray(index);
1069 }
1070 else
1071 {
1072 gles1.setClientStateEnabled(attrib, false);
1073 context->disableVertexAttribArray(index);
1074 }
1075 }
1076
1077 for (unsigned int i = 0; i < kTexUnitCount; i++)
1078 {
1079 int index = TexCoordArrayIndex(i);
1080
1081 if (mask.test(index))
1082 {
1083 gles1.setTexCoordArrayEnabled(i, true);
1084 context->enableVertexAttribArray(index);
1085 }
1086 else
1087 {
1088 gles1.setTexCoordArrayEnabled(i, false);
1089 context->disableVertexAttribArray(index);
1090 }
1091 }
1092 }
1093
1094 } // namespace gl
1095