aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrGpuGLFixed.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrGpuGLFixed.cpp')
-rw-r--r--src/gpu/GrGpuGLFixed.cpp382
1 files changed, 382 insertions, 0 deletions
diff --git a/src/gpu/GrGpuGLFixed.cpp b/src/gpu/GrGpuGLFixed.cpp
new file mode 100644
index 0000000000..336b687be8
--- /dev/null
+++ b/src/gpu/GrGpuGLFixed.cpp
@@ -0,0 +1,382 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#include "GrGLConfig.h"
+
+#include "GrGpuGLFixed.h"
+#include "GrGpuVertex.h"
+
+#define SKIP_CACHE_CHECK true
+
+struct GrGpuMatrix {
+ GrGLfloat fMat[16];
+
+ void reset() {
+ Gr_bzero(fMat, sizeof(fMat));
+ fMat[0] = fMat[5] = fMat[10] = fMat[15] = GR_Scalar1;
+ }
+
+ void set(const GrMatrix& m) {
+ Gr_bzero(fMat, sizeof(fMat));
+ fMat[0] = GrScalarToFloat(m[GrMatrix::kMScaleX]);
+ fMat[4] = GrScalarToFloat(m[GrMatrix::kMSkewX]);
+ fMat[12] = GrScalarToFloat(m[GrMatrix::kMTransX]);
+
+ fMat[1] = GrScalarToFloat(m[GrMatrix::kMSkewY]);
+ fMat[5] = GrScalarToFloat(m[GrMatrix::kMScaleY]);
+ fMat[13] = GrScalarToFloat(m[GrMatrix::kMTransY]);
+
+ fMat[3] = GrScalarToFloat(m[GrMatrix::kMPersp0]);
+ fMat[7] = GrScalarToFloat(m[GrMatrix::kMPersp1]);
+ fMat[15] = GrScalarToFloat(m[GrMatrix::kMPersp2]);
+
+ fMat[10] = 1.f; // z-scale
+ }
+};
+
+// these must match the order in the corresponding enum in GrGpu.h
+static const GrGLenum gMatrixMode2Enum[] = {
+ GR_GL_MODELVIEW, GR_GL_TEXTURE
+};
+
+#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
+///////////////////////////////////////////////////////////////////////////////
+
+namespace {
+GrGLBinding get_binding_in_use(const GrGLInterface* gl) {
+ if (gl->supportsDesktop()) {
+ return kDesktop_GrGLBinding;
+ } else {
+ GrAssert(gl->supportsES1());
+ return kES1_GrGLBinding;
+ }
+}
+}
+
+GrGpuGLFixed::GrGpuGLFixed(const GrGLInterface* gl)
+ : GrGpuGL(gl, get_binding_in_use(gl)) {
+}
+
+GrGpuGLFixed::~GrGpuGLFixed() {
+}
+
+void GrGpuGLFixed::resetContext() {
+ INHERITED::resetContext();
+
+ GL_CALL(Disable(GR_GL_TEXTURE_2D));
+
+ for (int s = 0; s < kNumStages; ++s) {
+ setTextureUnit(s);
+ GL_CALL(EnableClientState(GR_GL_VERTEX_ARRAY));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_TEXTURE_ENV_MODE,
+ GR_GL_COMBINE));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_COMBINE_RGB,
+ GR_GL_MODULATE));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_SRC0_RGB,
+ GR_GL_TEXTURE0+s));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_SRC1_RGB,
+ GR_GL_PREVIOUS));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_OPERAND1_RGB,
+ GR_GL_SRC_COLOR));
+
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_COMBINE_ALPHA,
+ GR_GL_MODULATE));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_SRC0_ALPHA,
+ GR_GL_TEXTURE0+s));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_OPERAND0_ALPHA,
+ GR_GL_SRC_ALPHA));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_SRC1_ALPHA,
+ GR_GL_PREVIOUS));
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_OPERAND1_ALPHA,
+ GR_GL_SRC_ALPHA));
+
+ // color oprand0 changes between GL_SRC_COLR and GL_SRC_ALPHA depending
+ // upon whether we have a (premultiplied) RGBA texture or just an ALPHA
+ // texture, e.g.:
+ //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1;
+ }
+
+ fHWGeometryState.fVertexLayout = 0;
+ fHWGeometryState.fVertexOffset = ~0;
+ GL_CALL(EnableClientState(GR_GL_VERTEX_ARRAY));
+ GL_CALL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
+ GL_CALL(ShadeModel(GR_GL_FLAT));
+ GL_CALL(DisableClientState(GR_GL_COLOR_ARRAY));
+
+ GL_CALL(PointSize(1.f));
+
+ GrGLClearErr(this->glInterface());
+ fTextVerts = false;
+
+ fBaseVertex = 0xffffffff;
+}
+
+
+void GrGpuGLFixed::flushProjectionMatrix() {
+ float mat[16];
+ Gr_bzero(mat, sizeof(mat));
+
+ GrAssert(NULL != fCurrDrawState.fRenderTarget);
+
+ mat[0] = 2.f / fCurrDrawState.fRenderTarget->width();
+ mat[5] = -2.f / fCurrDrawState.fRenderTarget->height();
+ mat[10] = -1.f;
+ mat[15] = 1;
+
+ mat[12] = -1.f;
+ mat[13] = 1.f;
+
+ GL_CALL(MatrixMode(GR_GL_PROJECTION));
+ GL_CALL(LoadMatrixf(mat));
+}
+
+bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
+
+ bool usingTextures[kNumStages];
+
+ for (int s = 0; s < kNumStages; ++s) {
+ usingTextures[s] = this->isStageEnabled(s);
+ if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
+ unimpl("Fixed pipe doesn't support radial/sweep gradients");
+ return false;
+ }
+ }
+
+ if (kES1_GrGLBinding == this->glBinding()) {
+ if (BlendCoeffReferencesConstant(fCurrDrawState.fSrcBlend) ||
+ BlendCoeffReferencesConstant(fCurrDrawState.fDstBlend)) {
+ unimpl("ES1 doesn't support blend constant");
+ return false;
+ }
+ }
+
+ if (!flushGLStateCommon(type)) {
+ return false;
+ }
+
+ GrBlendCoeff srcCoeff, dstCoeff;
+ if (kSkipDraw_BlendOptFlag &
+ this->getBlendOpts(false, &srcCoeff, &dstCoeff)) {
+ return false;
+ }
+
+ this->flushBlend(type, srcCoeff, dstCoeff);
+
+ if (fDirtyFlags.fRenderTargetChanged) {
+ flushProjectionMatrix();
+ }
+
+ for (int s = 0; s < kNumStages; ++s) {
+ bool wasUsingTexture = StageWillBeUsed(s, fHWGeometryState.fVertexLayout, fHWDrawState);
+ if (usingTextures[s] != wasUsingTexture) {
+ setTextureUnit(s);
+ if (usingTextures[s]) {
+ GL_CALL(Enable(GR_GL_TEXTURE_2D));
+ } else {
+ GL_CALL(Disable(GR_GL_TEXTURE_2D));
+ }
+ }
+ }
+
+ uint32_t vertColor = (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit);
+ uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
+ kColor_VertexLayoutBit);
+
+ if (vertColor != prevVertColor) {
+ if (vertColor) {
+ GL_CALL(ShadeModel(GR_GL_SMOOTH));
+ // invalidate the immediate mode color
+ fHWDrawState.fColor = GrColor_ILLEGAL;
+ } else {
+ GL_CALL(ShadeModel(GR_GL_FLAT));
+ }
+ }
+
+
+ if (!vertColor && fHWDrawState.fColor != fCurrDrawState.fColor) {
+ GL_CALL(Color4ub(GrColorUnpackR(fCurrDrawState.fColor),
+ GrColorUnpackG(fCurrDrawState.fColor),
+ GrColorUnpackB(fCurrDrawState.fColor),
+ GrColorUnpackA(fCurrDrawState.fColor)));
+ fHWDrawState.fColor = fCurrDrawState.fColor;
+ }
+
+ // set texture environment, decide whether we are modulating by RGB or A.
+ for (int s = 0; s < kNumStages; ++s) {
+ if (usingTextures[s]) {
+ GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
+ if (NULL != texture) {
+ TextureEnvRGBOperands nextRGBOperand0 =
+ (GrPixelConfigIsAlphaOnly(texture->config())) ?
+ kAlpha_TextureEnvRGBOperand :
+ kColor_TextureEnvRGBOperand;
+ if (fHWRGBOperand0[s] != nextRGBOperand0) {
+ setTextureUnit(s);
+ GL_CALL(TexEnvi(GR_GL_TEXTURE_ENV,
+ GR_GL_OPERAND0_RGB,
+ (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
+ GR_GL_SRC_ALPHA :
+ GR_GL_SRC_COLOR));
+ fHWRGBOperand0[s] = nextRGBOperand0;
+ }
+
+ if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
+ (fHWDrawState.fSamplerStates[s].getMatrix() !=
+ getSamplerMatrix(s))) {
+
+ GrMatrix texMat = getSamplerMatrix(s);
+ AdjustTextureMatrix(texture,
+ GrSamplerState::kNormal_SampleMode,
+ &texMat);
+ GrGpuMatrix glm;
+ glm.set(texMat);
+ setTextureUnit(s);
+ GL_CALL(MatrixMode(GR_GL_TEXTURE));
+ GL_CALL(LoadMatrixf(glm.fMat));
+ recordHWSamplerMatrix(s, getSamplerMatrix(s));
+ }
+ } else {
+ GrAssert(!"Rendering with texture vert flag set but no bound texture");
+ return false;
+ }
+ }
+ }
+
+ if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
+ GrGpuMatrix glm;
+ glm.set(fCurrDrawState.fViewMatrix);
+ GL_CALL(MatrixMode(GR_GL_MODELVIEW));
+ GL_CALL(LoadMatrixf(glm.fMat));
+ fHWDrawState.fViewMatrix =
+ fCurrDrawState.fViewMatrix;
+ }
+ resetDirtyFlags();
+ return true;
+}
+
+void GrGpuGLFixed::setupGeometry(int* startVertex,
+ int* startIndex,
+ int vertexCount,
+ int indexCount) {
+
+ int newColorOffset;
+ int newCoverageOffset;
+ int newTexCoordOffsets[kNumStages];
+ int newEdgeOffset;
+
+ GrGLsizei newStride = VertexSizeAndOffsetsByStage(this->getGeomSrc().fVertexLayout,
+ newTexCoordOffsets,
+ &newColorOffset,
+ &newCoverageOffset,
+ &newEdgeOffset);
+ GrAssert(-1 == newEdgeOffset); // not supported by fixed pipe
+ GrAssert(-1 == newCoverageOffset); // not supported by fixed pipe
+
+ int oldColorOffset;
+ int oldCoverageOffset;
+ int oldTexCoordOffsets[kNumStages];
+ int oldEdgeOffset;
+ GrGLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
+ oldTexCoordOffsets,
+ &oldColorOffset,
+ &oldCoverageOffset,
+ &oldEdgeOffset);
+ GrAssert(-1 == oldEdgeOffset);
+ GrAssert(-1 == oldCoverageOffset);
+
+ bool indexed = NULL != startIndex;
+
+ int extraVertexOffset;
+ int extraIndexOffset;
+ setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
+
+ GrGLenum scalarType;
+ if (this->getGeomSrc().fVertexLayout & kTextFormat_VertexLayoutBit) {
+ scalarType = GrGLTextType;
+ } else {
+ scalarType = GrGLType;
+ }
+
+ size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
+ *startVertex = 0;
+ if (indexed) {
+ *startIndex += extraIndexOffset;
+ }
+
+ // all the Pointers must be set if any of these are true
+ bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
+ vertexOffset != fHWGeometryState.fVertexOffset ||
+ newStride != oldStride;
+
+ // position and tex coord offsets change if above conditions are true
+ // or the type changed based on text vs nontext type coords.
+ bool posAndTexChange = allOffsetsChange ||
+ ((GrGLTextType != GrGLType) &&
+ (kTextFormat_VertexLayoutBit &
+ (fHWGeometryState.fVertexLayout ^
+ this->getGeomSrc().fVertexLayout)));
+
+ if (posAndTexChange) {
+ GL_CALL(VertexPointer(2, scalarType,
+ newStride, (GrGLvoid*)vertexOffset));
+ fHWGeometryState.fVertexOffset = vertexOffset;
+ }
+
+ for (int s = 0; s < kNumStages; ++s) {
+ // need to enable array if tex coord offset is 0
+ // (using positions as coords)
+ if (newTexCoordOffsets[s] >= 0) {
+ GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset +
+ newTexCoordOffsets[s]);
+ if (oldTexCoordOffsets[s] < 0) {
+ GL_CALL(ClientActiveTexture(GR_GL_TEXTURE0+s));
+ GL_CALL(EnableClientState(GR_GL_TEXTURE_COORD_ARRAY));
+ GL_CALL(TexCoordPointer(2, scalarType,
+ newStride, texCoordOffset));
+ } else if (posAndTexChange ||
+ newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
+ GL_CALL(ClientActiveTexture(GR_GL_TEXTURE0+s));
+ GL_CALL(TexCoordPointer(2, scalarType,
+ newStride, texCoordOffset));
+ }
+ } else if (oldTexCoordOffsets[s] >= 0) {
+ GL_CALL(ClientActiveTexture(GR_GL_TEXTURE0+s));
+ GL_CALL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
+ }
+ }
+
+ if (newColorOffset > 0) {
+ GrGLvoid* colorOffset = (GrGLvoid*)(vertexOffset + newColorOffset);
+ if (oldColorOffset <= 0) {
+ GL_CALL(EnableClientState(GR_GL_COLOR_ARRAY));
+ GL_CALL(ColorPointer(4, GR_GL_UNSIGNED_BYTE,
+ newStride, colorOffset));
+ } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
+ GL_CALL(ColorPointer(4, GR_GL_UNSIGNED_BYTE,
+ newStride, colorOffset));
+ }
+ } else if (oldColorOffset > 0) {
+ GL_CALL(DisableClientState(GR_GL_COLOR_ARRAY));
+ }
+
+ fHWGeometryState.fVertexLayout = this->getGeomSrc().fVertexLayout;
+ fHWGeometryState.fArrayPtrsDirty = false;
+}