Move copy-surface-as-draw fallback to GrGLGpu.
Review URL: https://codereview.chromium.org/1144433002
This commit is contained in:
parent
5b5ddd73b4
commit
5df6fee929
@ -100,13 +100,10 @@ bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuil
|
||||
return false;
|
||||
}
|
||||
SkIPoint dstPoint = {0, 0};
|
||||
if (this->copySurface(copy, rt, copyRect, dstPoint)) {
|
||||
dstCopy->setTexture(copy);
|
||||
dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
this->copySurface(copy, rt, copyRect, dstPoint);
|
||||
dstCopy->setTexture(copy);
|
||||
dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrDrawTarget::flush() {
|
||||
@ -421,7 +418,7 @@ bool clip_srcrect_and_dstpoint(const GrSurface* dst,
|
||||
}
|
||||
}
|
||||
|
||||
bool GrDrawTarget::copySurface(GrSurface* dst,
|
||||
void GrDrawTarget::copySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
@ -437,56 +434,10 @@ bool GrDrawTarget::copySurface(GrSurface* dst,
|
||||
dstPoint,
|
||||
&clippedSrcRect,
|
||||
&clippedDstPoint)) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)) {
|
||||
this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
GrRenderTarget* rt = dst->asRenderTarget();
|
||||
GrTexture* tex = src->asTexture();
|
||||
|
||||
if ((dst == src) || !rt || !tex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrPipelineBuilder pipelineBuilder;
|
||||
pipelineBuilder.setRenderTarget(rt);
|
||||
SkMatrix matrix;
|
||||
matrix.setTranslate(SkIntToScalar(clippedSrcRect.fLeft - clippedDstPoint.fX),
|
||||
SkIntToScalar(clippedSrcRect.fTop - clippedDstPoint.fY));
|
||||
matrix.postIDiv(tex->width(), tex->height());
|
||||
pipelineBuilder.addColorTextureProcessor(tex, matrix);
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(clippedDstPoint.fX,
|
||||
clippedDstPoint.fY,
|
||||
clippedSrcRect.width(),
|
||||
clippedSrcRect.height());
|
||||
this->drawSimpleRect(&pipelineBuilder, GrColor_WHITE, SkMatrix::I(), dstRect);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrDrawTarget::canCopySurface(const GrSurface* dst,
|
||||
const GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(dst);
|
||||
SkASSERT(src);
|
||||
|
||||
SkIRect clippedSrcRect;
|
||||
SkIPoint clippedDstPoint;
|
||||
// If the rect is outside the src or dst then we're guaranteed success
|
||||
if (!clip_srcrect_and_dstpoint(dst,
|
||||
src,
|
||||
srcRect,
|
||||
dstPoint,
|
||||
&clippedSrcRect,
|
||||
&clippedDstPoint)) {
|
||||
return true;
|
||||
}
|
||||
return ((dst != src) && dst->asRenderTarget() && src->asTexture()) ||
|
||||
this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
|
||||
this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
|
||||
}
|
||||
|
||||
void GrDrawTarget::setupPipeline(const PipelineInfo& pipelineInfo,
|
||||
|
@ -178,24 +178,14 @@ public:
|
||||
* copied are specified by srcRect. They are copied to a rect of the same
|
||||
* size in dst with top left at dstPoint. If the src rect is clipped by the
|
||||
* src bounds then pixel values in the dst rect corresponding to area clipped
|
||||
* by the src rect are not overwritten. This method can fail and return false
|
||||
* by the src rect are not overwritten. This method is not guaranteed to succeed
|
||||
* depending on the type of surface, configs, etc, and the backend-specific
|
||||
* limitations. If rect is clipped out entirely by the src or dst bounds then
|
||||
* true is returned since there is no actual copy necessary to succeed.
|
||||
* limitations.
|
||||
*/
|
||||
bool copySurface(GrSurface* dst,
|
||||
void copySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
/**
|
||||
* Function that determines whether a copySurface call would succeed without actually
|
||||
* performing the copy.
|
||||
*/
|
||||
bool canCopySurface(const GrSurface* dst,
|
||||
const GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
|
||||
/**
|
||||
* Release any resources that are cached but not currently in use. This
|
||||
* is intended to give an application some recourse when resources are low.
|
||||
|
@ -257,16 +257,6 @@ public:
|
||||
const GrPipeline&,
|
||||
const GrBatchTracker&) const = 0;
|
||||
|
||||
// Called to determine whether a copySurface call would succeed or not. Derived
|
||||
// classes must keep this consistent with their implementation of onCopySurface(). Fallbacks
|
||||
// to issuing a draw from the src to dst take place at the GrDrawTarget level and this function
|
||||
// should only return true if a faster copy path exists. The rect and point are pre-clipped. The
|
||||
// src rect and implied dst rect are guaranteed to be within the src/dst bounds and non-empty.
|
||||
virtual bool canCopySurface(const GrSurface* dst,
|
||||
const GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) = 0;
|
||||
|
||||
// Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst
|
||||
// take place at the GrDrawTarget level and this function implement faster copy paths. The rect
|
||||
// and point are pre-clipped. The src rect and implied dst rect are guaranteed to be within the
|
||||
|
@ -121,7 +121,6 @@ void GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(this->getGpu()->canCopySurface(dst, src, srcRect, dstPoint));
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordCopySurface(dst, src, srcRect, dstPoint);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
@ -155,11 +155,6 @@ public:
|
||||
|
||||
void discard(GrRenderTarget*) override {}
|
||||
|
||||
bool canCopySurface(const GrSurface* dst,
|
||||
const GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) override { return false; };
|
||||
|
||||
bool copySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
|
@ -942,6 +942,7 @@ GrGLSLCaps::GrGLSLCaps(const GrGLSLCaps& caps) : GrShaderCaps() {
|
||||
|
||||
GrGLSLCaps& GrGLSLCaps::operator= (const GrGLSLCaps& caps) {
|
||||
INHERITED::operator=(caps);
|
||||
fGLSLGeneration = caps.fGLSLGeneration;
|
||||
fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
|
||||
fFBFetchSupport = caps.fFBFetchSupport;
|
||||
fFBFetchNeedsCustomOutput = caps.fFBFetchNeedsCustomOutput;
|
||||
@ -960,6 +961,8 @@ bool GrGLSLCaps::init(const GrGLContextInfo& ctxInfo,
|
||||
return false;
|
||||
}
|
||||
|
||||
fGLSLGeneration = ctxInfo.glslGeneration();
|
||||
|
||||
GrGLStandard standard = ctxInfo.standard();
|
||||
GrGLVersion version = ctxInfo.version();
|
||||
|
||||
|
@ -374,6 +374,7 @@ private:
|
||||
typedef GrDrawTargetCaps INHERITED;
|
||||
};
|
||||
|
||||
#include "GrGLSL.h"
|
||||
|
||||
class GrGLSLCaps : public GrShaderCaps {
|
||||
public:
|
||||
@ -438,6 +439,12 @@ public:
|
||||
bool mustEnableSpecificAdvBlendEqs() const {
|
||||
return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
|
||||
}
|
||||
|
||||
bool mustDeclareFragmentShaderOutput() const {
|
||||
return fGLSLGeneration > k110_GrGLSLGeneration;
|
||||
}
|
||||
|
||||
GrGLSLGeneration generation() const { return fGLSLGeneration; }
|
||||
|
||||
/**
|
||||
* Returns a string containing the caps info.
|
||||
@ -448,6 +455,8 @@ private:
|
||||
// Must be called after fGeometryShaderSupport is initialized.
|
||||
void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*);
|
||||
|
||||
GrGLSLGeneration fGLSLGeneration;
|
||||
|
||||
bool fDropsTileOnZeroDivide : 1;
|
||||
bool fFBFetchSupport : 1;
|
||||
bool fFBFetchNeedsCustomOutput : 1;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "GrTexturePriv.h"
|
||||
#include "GrTypes.h"
|
||||
#include "GrVertices.h"
|
||||
#include "builders/GrGLShaderStringBuilder.h"
|
||||
#include "SkStrokeRec.h"
|
||||
#include "SkTemplates.h"
|
||||
|
||||
@ -200,13 +201,14 @@ GrGLGpu::GrGLGpu(const GrGLContext& ctx, GrContext* context)
|
||||
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
|
||||
fPathRendering.reset(new GrGLPathRendering(this));
|
||||
}
|
||||
|
||||
this->createCopyProgram();
|
||||
}
|
||||
|
||||
GrGLGpu::~GrGLGpu() {
|
||||
if (0 != fHWProgramID) {
|
||||
// detach the current program so there is no confusion on OpenGL's part
|
||||
// that we want it to be deleted
|
||||
SkASSERT(fHWProgramID == fCurrentProgram->programID());
|
||||
GL_CALL(UseProgram(0));
|
||||
}
|
||||
|
||||
@ -220,6 +222,14 @@ GrGLGpu::~GrGLGpu() {
|
||||
GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
|
||||
}
|
||||
|
||||
if (0 != fCopyProgram.fArrayBuffer) {
|
||||
GL_CALL(DeleteBuffers(1, &fCopyProgram.fArrayBuffer));
|
||||
}
|
||||
|
||||
if (0 != fCopyProgram.fProgram) {
|
||||
GL_CALL(DeleteProgram(fCopyProgram.fProgram));
|
||||
}
|
||||
|
||||
delete fProgramCache;
|
||||
}
|
||||
|
||||
@ -230,6 +240,8 @@ void GrGLGpu::contextAbandoned() {
|
||||
fTempSrcFBOID = 0;
|
||||
fTempDstFBOID = 0;
|
||||
fStencilClearFBOID = 0;
|
||||
fCopyProgram.fArrayBuffer = 0;
|
||||
fCopyProgram.fProgram = 0;
|
||||
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
|
||||
this->glPathRendering()->abandonGpuResources();
|
||||
}
|
||||
@ -1417,15 +1429,13 @@ bool GrGLGpu::flushGLState(const DrawArgs& args) {
|
||||
this->flushColorWrite(blendInfo.fWriteColor);
|
||||
this->flushDrawFace(pipeline.getDrawFace());
|
||||
|
||||
fCurrentProgram.reset(fProgramCache->getProgram(args));
|
||||
if (NULL == fCurrentProgram.get()) {
|
||||
SkAutoTUnref<GrGLProgram> program(fProgramCache->refProgram(args));
|
||||
if (!program) {
|
||||
GrContextDebugf(this->getContext(), "Failed to create program!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
fCurrentProgram.get()->ref();
|
||||
|
||||
GrGLuint programID = fCurrentProgram->programID();
|
||||
GrGLuint programID = program->programID();
|
||||
if (fHWProgramID != programID) {
|
||||
GL_CALL(UseProgram(programID));
|
||||
fHWProgramID = programID;
|
||||
@ -1435,7 +1445,7 @@ bool GrGLGpu::flushGLState(const DrawArgs& args) {
|
||||
this->flushBlend(blendInfo);
|
||||
}
|
||||
|
||||
fCurrentProgram->setData(*args.fPrimitiveProcessor, pipeline, *args.fBatchTracker);
|
||||
program->setData(*args.fPrimitiveProcessor, pipeline, *args.fBatchTracker);
|
||||
|
||||
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
|
||||
this->flushStencil(pipeline.getStencil());
|
||||
@ -1490,7 +1500,7 @@ void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
|
||||
GrVertexAttribType attribType = attrib.fType;
|
||||
attribState->set(this,
|
||||
attribIndex,
|
||||
vbuf,
|
||||
vbuf->bufferID(),
|
||||
GrGLAttribTypeToLayout(attribType).fCount,
|
||||
GrGLAttribTypeToLayout(attribType).fType,
|
||||
GrGLAttribTypeToLayout(attribType).fNormalized,
|
||||
@ -2618,7 +2628,16 @@ void GrGLGpu::unbindTextureFromFBO(GrGLenum fboTarget) {
|
||||
}
|
||||
|
||||
bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) {
|
||||
// In here we look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
|
||||
// If the src is a texture, we can implement the blit as a draw assuming the config is
|
||||
// renderable.
|
||||
if (src->asTexture() && this->caps()->isConfigRenderable(src->config(), false)) {
|
||||
desc->fOrigin = kDefault_GrSurfaceOrigin;
|
||||
desc->fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
desc->fConfig = src->config();
|
||||
return true;
|
||||
}
|
||||
|
||||
// We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
|
||||
// possible and we return false to fallback to creating a render target dst for render-to-
|
||||
// texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo
|
||||
// creation. It isn't clear that avoiding temporary fbo creation is actually optimal.
|
||||
@ -2664,127 +2683,295 @@ bool GrGLGpu::copySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
bool copied = false;
|
||||
if (can_copy_texsubimage(dst, src, this)) {
|
||||
GrGLuint srcFBO;
|
||||
GrGLIRect srcVP;
|
||||
srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
|
||||
GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture());
|
||||
SkASSERT(dstTex);
|
||||
// We modified the bound FBO
|
||||
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
|
||||
GrGLIRect srcGLRect;
|
||||
srcGLRect.setRelativeTo(srcVP,
|
||||
srcRect.fLeft,
|
||||
srcRect.fTop,
|
||||
srcRect.width(),
|
||||
srcRect.height(),
|
||||
src->origin());
|
||||
|
||||
this->setScratchTextureUnit();
|
||||
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, dstTex->textureID()));
|
||||
GrGLint dstY;
|
||||
if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
|
||||
dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
|
||||
} else {
|
||||
dstY = dstPoint.fY;
|
||||
}
|
||||
GL_CALL(CopyTexSubImage2D(GR_GL_TEXTURE_2D, 0,
|
||||
dstPoint.fX, dstY,
|
||||
srcGLRect.fLeft, srcGLRect.fBottom,
|
||||
srcGLRect.fWidth, srcGLRect.fHeight));
|
||||
copied = true;
|
||||
if (srcFBO) {
|
||||
this->unbindTextureFromFBO(GR_GL_FRAMEBUFFER);
|
||||
}
|
||||
} else if (can_blit_framebuffer(dst, src, this)) {
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
|
||||
srcRect.width(), srcRect.height());
|
||||
bool selfOverlap = false;
|
||||
if (dst == src) {
|
||||
selfOverlap = SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect);
|
||||
}
|
||||
|
||||
if (!selfOverlap) {
|
||||
GrGLuint dstFBO;
|
||||
GrGLuint srcFBO;
|
||||
GrGLIRect dstVP;
|
||||
GrGLIRect srcVP;
|
||||
dstFBO = this->bindSurfaceAsFBO(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP,
|
||||
kDst_TempFBOTarget);
|
||||
srcFBO = this->bindSurfaceAsFBO(src, GR_GL_READ_FRAMEBUFFER, &srcVP,
|
||||
kSrc_TempFBOTarget);
|
||||
// We modified the bound FBO
|
||||
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
|
||||
GrGLIRect srcGLRect;
|
||||
GrGLIRect dstGLRect;
|
||||
srcGLRect.setRelativeTo(srcVP,
|
||||
srcRect.fLeft,
|
||||
srcRect.fTop,
|
||||
srcRect.width(),
|
||||
srcRect.height(),
|
||||
src->origin());
|
||||
dstGLRect.setRelativeTo(dstVP,
|
||||
dstRect.fLeft,
|
||||
dstRect.fTop,
|
||||
dstRect.width(),
|
||||
dstRect.height(),
|
||||
dst->origin());
|
||||
|
||||
// BlitFrameBuffer respects the scissor, so disable it.
|
||||
this->disableScissor();
|
||||
|
||||
GrGLint srcY0;
|
||||
GrGLint srcY1;
|
||||
// Does the blit need to y-mirror or not?
|
||||
if (src->origin() == dst->origin()) {
|
||||
srcY0 = srcGLRect.fBottom;
|
||||
srcY1 = srcGLRect.fBottom + srcGLRect.fHeight;
|
||||
} else {
|
||||
srcY0 = srcGLRect.fBottom + srcGLRect.fHeight;
|
||||
srcY1 = srcGLRect.fBottom;
|
||||
}
|
||||
GL_CALL(BlitFramebuffer(srcGLRect.fLeft,
|
||||
srcY0,
|
||||
srcGLRect.fLeft + srcGLRect.fWidth,
|
||||
srcY1,
|
||||
dstGLRect.fLeft,
|
||||
dstGLRect.fBottom,
|
||||
dstGLRect.fLeft + dstGLRect.fWidth,
|
||||
dstGLRect.fBottom + dstGLRect.fHeight,
|
||||
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
|
||||
if (dstFBO) {
|
||||
this->unbindTextureFromFBO(GR_GL_DRAW_FRAMEBUFFER);
|
||||
}
|
||||
if (srcFBO) {
|
||||
this->unbindTextureFromFBO(GR_GL_READ_FRAMEBUFFER);
|
||||
}
|
||||
copied = true;
|
||||
}
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
bool GrGLGpu::canCopySurface(const GrSurface* dst,
|
||||
const GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
// This mirrors the logic in onCopySurface.
|
||||
if (can_copy_texsubimage(dst, src, this)) {
|
||||
if (src->asTexture() && dst->asRenderTarget()) {
|
||||
this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (can_copy_texsubimage(dst, src, this)) {
|
||||
this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (can_blit_framebuffer(dst, src, this)) {
|
||||
if (dst == src) {
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
|
||||
srcRect.width(), srcRect.height());
|
||||
if(!SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void GrGLGpu::createCopyProgram() {
|
||||
const char* version = GrGetGLSLVersionDecl(this->ctxInfo());
|
||||
|
||||
GrGLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
|
||||
GrGLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
|
||||
GrShaderVar::kUniform_TypeModifier);
|
||||
GrGLShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
|
||||
GrGLShaderVar uTexture("u_texture", kSampler2D_GrSLType, GrShaderVar::kUniform_TypeModifier);
|
||||
GrGLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier);
|
||||
GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
|
||||
|
||||
SkString vshaderTxt(version);
|
||||
aVertex.appendDecl(this->ctxInfo(), &vshaderTxt);
|
||||
vshaderTxt.append(";");
|
||||
uTexCoordXform.appendDecl(this->ctxInfo(), &vshaderTxt);
|
||||
vshaderTxt.append(";");
|
||||
uPosXform.appendDecl(this->ctxInfo(), &vshaderTxt);
|
||||
vshaderTxt.append(";");
|
||||
vTexCoord.appendDecl(this->ctxInfo(), &vshaderTxt);
|
||||
vshaderTxt.append(";");
|
||||
|
||||
vshaderTxt.append(
|
||||
"// Copy Program VS\n"
|
||||
"void main() {"
|
||||
" v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
|
||||
" gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
|
||||
" gl_Position.zw = vec2(0, 1);"
|
||||
"}"
|
||||
);
|
||||
|
||||
SkString fshaderTxt(version);
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, this->glStandard(),
|
||||
&fshaderTxt);
|
||||
vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
|
||||
vTexCoord.appendDecl(this->ctxInfo(), &fshaderTxt);
|
||||
fshaderTxt.append(";");
|
||||
uTexture.appendDecl(this->ctxInfo(), &fshaderTxt);
|
||||
fshaderTxt.append(";");
|
||||
const char* fsOutName;
|
||||
if (this->glCaps().glslCaps()->mustDeclareFragmentShaderOutput()) {
|
||||
oFragColor.appendDecl(this->ctxInfo(), &fshaderTxt);
|
||||
fshaderTxt.append(";");
|
||||
fsOutName = oFragColor.c_str();
|
||||
} else {
|
||||
fsOutName = "gl_FragColor";
|
||||
}
|
||||
fshaderTxt.appendf(
|
||||
"// Copy Program FS\n"
|
||||
"void main() {"
|
||||
" %s = %s(u_texture, v_texCoord);"
|
||||
"}",
|
||||
fsOutName,
|
||||
GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration())
|
||||
);
|
||||
|
||||
GL_CALL_RET(fCopyProgram.fProgram, CreateProgram());
|
||||
const char* str;
|
||||
GrGLint length;
|
||||
|
||||
str = vshaderTxt.c_str();
|
||||
length = SkToInt(vshaderTxt.size());
|
||||
GrGLuint vshader = GrGLCompileAndAttachShader(fGLContext, fCopyProgram.fProgram,
|
||||
GR_GL_VERTEX_SHADER, &str, &length, 1, &fStats);
|
||||
|
||||
str = fshaderTxt.c_str();
|
||||
length = SkToInt(fshaderTxt.size());
|
||||
GrGLuint fshader = GrGLCompileAndAttachShader(fGLContext, fCopyProgram.fProgram,
|
||||
GR_GL_FRAGMENT_SHADER, &str, &length, 1, &fStats);
|
||||
|
||||
GL_CALL(LinkProgram(fCopyProgram.fProgram));
|
||||
|
||||
GL_CALL_RET(fCopyProgram.fTextureUniform, GetUniformLocation(fCopyProgram.fProgram,
|
||||
"u_texture"));
|
||||
GL_CALL_RET(fCopyProgram.fPosXformUniform, GetUniformLocation(fCopyProgram.fProgram,
|
||||
"u_posXform"));
|
||||
GL_CALL_RET(fCopyProgram.fTexCoordXformUniform, GetUniformLocation(fCopyProgram.fProgram,
|
||||
"u_texCoordXform"));
|
||||
|
||||
GL_CALL(BindAttribLocation(fCopyProgram.fProgram, 0, "a_vertex"));
|
||||
|
||||
GL_CALL(DeleteShader(vshader));
|
||||
GL_CALL(DeleteShader(fshader));
|
||||
|
||||
GL_CALL(GenBuffers(1, &fCopyProgram.fArrayBuffer));
|
||||
fHWGeometryState.setVertexBufferID(this, fCopyProgram.fArrayBuffer);
|
||||
static const GrGLfloat vdata[] = {
|
||||
0, 0,
|
||||
0, 1,
|
||||
1, 0,
|
||||
1, 1
|
||||
};
|
||||
GL_ALLOC_CALL(this->glInterface(),
|
||||
BufferData(GR_GL_ARRAY_BUFFER,
|
||||
(GrGLsizeiptr) sizeof(vdata),
|
||||
vdata, // data ptr
|
||||
GR_GL_STATIC_DRAW));
|
||||
}
|
||||
|
||||
void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
int w = srcRect.width();
|
||||
int h = srcRect.height();
|
||||
|
||||
GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
|
||||
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
|
||||
this->bindTexture(0, params, srcTex);
|
||||
|
||||
GrGLRenderTarget* dstRT = static_cast<GrGLRenderTarget*>(dst->asRenderTarget());
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h);
|
||||
this->flushRenderTarget(dstRT, &dstRect);
|
||||
|
||||
GL_CALL(UseProgram(fCopyProgram.fProgram));
|
||||
fHWProgramID = fCopyProgram.fProgram;
|
||||
|
||||
fHWGeometryState.setVertexArrayID(this, 0);
|
||||
|
||||
GrGLAttribArrayState* attribs =
|
||||
fHWGeometryState.bindArrayAndBufferToDraw(this, fCopyProgram.fArrayBuffer);
|
||||
attribs->set(this, 0, fCopyProgram.fArrayBuffer, 2, GR_GL_FLOAT, false,
|
||||
2 * sizeof(GrGLfloat), 0);
|
||||
|
||||
|
||||
// dst rect edges in NDC (-1 to 1)
|
||||
int dw = dst->width();
|
||||
int dh = dst->height();
|
||||
GrGLfloat dx0 = 2.f * dstPoint.fX / dw - 1.f;
|
||||
GrGLfloat dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
|
||||
GrGLfloat dy0 = 2.f * dstPoint.fY / dh - 1.f;
|
||||
GrGLfloat dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
|
||||
if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
|
||||
dy0 = -dy0;
|
||||
dy1 = -dy1;
|
||||
}
|
||||
|
||||
// src rect edges in normalized texture space (0 to 1)
|
||||
int sw = src->width();
|
||||
int sh = src->height();
|
||||
GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft / sw;
|
||||
GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w) / sw;
|
||||
GrGLfloat sy0 = (GrGLfloat)srcRect.fTop / sh;
|
||||
GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h) / sh;
|
||||
if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
|
||||
sy0 = 1.f - sy0;
|
||||
sy1 = 1.f - sy1;
|
||||
}
|
||||
|
||||
GL_CALL(Uniform4f(fCopyProgram.fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
|
||||
GL_CALL(Uniform4f(fCopyProgram.fTexCoordXformUniform, sx1 - sx0, sy1 - sy0, sx0, sy0));
|
||||
GL_CALL(Uniform1i(fCopyProgram.fTextureUniform, 0));
|
||||
|
||||
GrXferProcessor::BlendInfo blendInfo;
|
||||
blendInfo.reset();
|
||||
this->flushBlend(blendInfo);
|
||||
this->flushColorWrite(true);
|
||||
this->flushDither(false);
|
||||
this->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace);
|
||||
this->flushHWAAState(dstRT, false);
|
||||
this->disableScissor();
|
||||
GrStencilSettings stencil;
|
||||
stencil.setDisabled();
|
||||
this->flushStencil(stencil);
|
||||
|
||||
GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
|
||||
void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(can_copy_texsubimage(dst, src, this));
|
||||
GrGLuint srcFBO;
|
||||
GrGLIRect srcVP;
|
||||
srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
|
||||
GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture());
|
||||
SkASSERT(dstTex);
|
||||
// We modified the bound FBO
|
||||
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
|
||||
GrGLIRect srcGLRect;
|
||||
srcGLRect.setRelativeTo(srcVP,
|
||||
srcRect.fLeft,
|
||||
srcRect.fTop,
|
||||
srcRect.width(),
|
||||
srcRect.height(),
|
||||
src->origin());
|
||||
|
||||
this->setScratchTextureUnit();
|
||||
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, dstTex->textureID()));
|
||||
GrGLint dstY;
|
||||
if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
|
||||
dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
|
||||
} else {
|
||||
dstY = dstPoint.fY;
|
||||
}
|
||||
GL_CALL(CopyTexSubImage2D(GR_GL_TEXTURE_2D, 0,
|
||||
dstPoint.fX, dstY,
|
||||
srcGLRect.fLeft, srcGLRect.fBottom,
|
||||
srcGLRect.fWidth, srcGLRect.fHeight));
|
||||
if (srcFBO) {
|
||||
this->unbindTextureFromFBO(GR_GL_FRAMEBUFFER);
|
||||
}
|
||||
}
|
||||
|
||||
bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(can_blit_framebuffer(dst, src, this));
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
|
||||
srcRect.width(), srcRect.height());
|
||||
if (dst == src) {
|
||||
if (SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
GrGLuint dstFBO;
|
||||
GrGLuint srcFBO;
|
||||
GrGLIRect dstVP;
|
||||
GrGLIRect srcVP;
|
||||
dstFBO = this->bindSurfaceAsFBO(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP,
|
||||
kDst_TempFBOTarget);
|
||||
srcFBO = this->bindSurfaceAsFBO(src, GR_GL_READ_FRAMEBUFFER, &srcVP,
|
||||
kSrc_TempFBOTarget);
|
||||
// We modified the bound FBO
|
||||
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
|
||||
GrGLIRect srcGLRect;
|
||||
GrGLIRect dstGLRect;
|
||||
srcGLRect.setRelativeTo(srcVP,
|
||||
srcRect.fLeft,
|
||||
srcRect.fTop,
|
||||
srcRect.width(),
|
||||
srcRect.height(),
|
||||
src->origin());
|
||||
dstGLRect.setRelativeTo(dstVP,
|
||||
dstRect.fLeft,
|
||||
dstRect.fTop,
|
||||
dstRect.width(),
|
||||
dstRect.height(),
|
||||
dst->origin());
|
||||
|
||||
// BlitFrameBuffer respects the scissor, so disable it.
|
||||
this->disableScissor();
|
||||
|
||||
GrGLint srcY0;
|
||||
GrGLint srcY1;
|
||||
// Does the blit need to y-mirror or not?
|
||||
if (src->origin() == dst->origin()) {
|
||||
srcY0 = srcGLRect.fBottom;
|
||||
srcY1 = srcGLRect.fBottom + srcGLRect.fHeight;
|
||||
} else {
|
||||
srcY0 = srcGLRect.fBottom + srcGLRect.fHeight;
|
||||
srcY1 = srcGLRect.fBottom;
|
||||
}
|
||||
GL_CALL(BlitFramebuffer(srcGLRect.fLeft,
|
||||
srcY0,
|
||||
srcGLRect.fLeft + srcGLRect.fWidth,
|
||||
srcY1,
|
||||
dstGLRect.fLeft,
|
||||
dstGLRect.fBottom,
|
||||
dstGLRect.fLeft + dstGLRect.fWidth,
|
||||
dstGLRect.fBottom + dstGLRect.fHeight,
|
||||
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
|
||||
if (dstFBO) {
|
||||
this->unbindTextureFromFBO(GR_GL_DRAW_FRAMEBUFFER);
|
||||
}
|
||||
if (srcFBO) {
|
||||
this->unbindTextureFromFBO(GR_GL_READ_FRAMEBUFFER);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) {
|
||||
@ -2832,26 +3019,52 @@ void GrGLGpu::didRemoveGpuTraceMarker() {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBuffersToDraw(
|
||||
GrGLGpu* gpu,
|
||||
const GrGLVertexBuffer* vbuffer,
|
||||
const GrGLIndexBuffer* ibuffer) {
|
||||
SkASSERT(vbuffer);
|
||||
GrGLuint vbufferID = vbuffer->bufferID();
|
||||
GrGLuint* ibufferIDPtr = NULL;
|
||||
GrGLuint ibufferID;
|
||||
if (ibuffer) {
|
||||
ibufferID = ibuffer->bufferID();
|
||||
ibufferIDPtr = &ibufferID;
|
||||
}
|
||||
return this->internalBind(gpu, vbufferID, ibufferIDPtr);
|
||||
}
|
||||
|
||||
GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBufferToDraw(GrGLGpu* gpu,
|
||||
GrGLuint vbufferID) {
|
||||
return this->internalBind(gpu, vbufferID, NULL);
|
||||
}
|
||||
|
||||
GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBuffersToDraw(GrGLGpu* gpu,
|
||||
GrGLuint vbufferID,
|
||||
GrGLuint ibufferID) {
|
||||
return this->internalBind(gpu, vbufferID, &ibufferID);
|
||||
}
|
||||
|
||||
GrGLAttribArrayState* GrGLGpu::HWGeometryState::internalBind(GrGLGpu* gpu,
|
||||
GrGLuint vbufferID,
|
||||
GrGLuint* ibufferID) {
|
||||
GrGLAttribArrayState* attribState;
|
||||
|
||||
// We use a vertex array if we're on a core profile and the verts are in a VBO.
|
||||
if (gpu->glCaps().isCoreProfile() && !vbuffer->isCPUBacked()) {
|
||||
if (gpu->glCaps().isCoreProfile() && 0 != vbufferID) {
|
||||
if (!fVBOVertexArray) {
|
||||
GrGLuint arrayID;
|
||||
GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
|
||||
int attrCount = gpu->glCaps().maxVertexAttributes();
|
||||
fVBOVertexArray = SkNEW_ARGS(GrGLVertexArray, (arrayID, attrCount));
|
||||
}
|
||||
attribState = fVBOVertexArray->bindWithIndexBuffer(gpu, ibuffer);
|
||||
if (ibufferID) {
|
||||
attribState = fVBOVertexArray->bindWithIndexBuffer(gpu, *ibufferID);
|
||||
} else {
|
||||
attribState = fVBOVertexArray->bind(gpu);
|
||||
}
|
||||
} else {
|
||||
if (ibuffer) {
|
||||
this->setIndexBufferIDOnDefaultVertexArray(gpu, ibuffer->bufferID());
|
||||
if (ibufferID) {
|
||||
this->setIndexBufferIDOnDefaultVertexArray(gpu, *ibufferID);
|
||||
} else {
|
||||
this->setVertexArrayID(gpu, 0);
|
||||
}
|
||||
|
@ -101,11 +101,6 @@ public:
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) override;
|
||||
|
||||
bool canCopySurface(const GrSurface* dst,
|
||||
const GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) override;
|
||||
|
||||
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
|
||||
|
||||
void buildProgramDesc(GrProgramDesc*,
|
||||
@ -183,6 +178,19 @@ private:
|
||||
// Subclasses should call this to flush the blend state.
|
||||
void flushBlend(const GrXferProcessor::BlendInfo& blendInfo);
|
||||
|
||||
void copySurfaceAsDraw(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
void copySurfaceAsCopyTexSubImage(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
bool copySurfaceAsBlitFramebuffer(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
|
||||
bool hasExtension(const char* ext) const { return fGLContext.hasExtension(ext); }
|
||||
|
||||
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
|
||||
@ -193,7 +201,7 @@ private:
|
||||
~ProgramCache();
|
||||
|
||||
void abandon();
|
||||
GrGLProgram* getProgram(const DrawArgs&);
|
||||
GrGLProgram* refProgram(const DrawArgs&);
|
||||
|
||||
private:
|
||||
enum {
|
||||
@ -294,11 +302,12 @@ private:
|
||||
|
||||
void unbindTextureFromFBO(GrGLenum fboTarget);
|
||||
|
||||
void createCopyProgram();
|
||||
|
||||
GrGLContext fGLContext;
|
||||
|
||||
// GL program-related state
|
||||
ProgramCache* fProgramCache;
|
||||
SkAutoTUnref<GrGLProgram> fCurrentProgram;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///@name Caching of GL State
|
||||
@ -420,7 +429,17 @@ private:
|
||||
const GrGLVertexBuffer* vbuffer,
|
||||
const GrGLIndexBuffer* ibuffer);
|
||||
|
||||
/** Variants of the above that takes GL buffer IDs. Note that 0 does not imply that a
|
||||
buffer won't be bound. The "default buffer" will be bound, which is used for client-side
|
||||
array rendering. */
|
||||
GrGLAttribArrayState* bindArrayAndBufferToDraw(GrGLGpu* gpu, GrGLuint vbufferID);
|
||||
GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGLGpu* gpu,
|
||||
GrGLuint vbufferID,
|
||||
GrGLuint ibufferID);
|
||||
|
||||
private:
|
||||
GrGLAttribArrayState* internalBind(GrGLGpu* gpu, GrGLuint vbufferID, GrGLuint* ibufferID);
|
||||
|
||||
GrGLuint fBoundVertexArrayID;
|
||||
GrGLuint fBoundVertexBufferID;
|
||||
bool fBoundVertexArrayIDIsValid;
|
||||
@ -454,6 +473,15 @@ private:
|
||||
}
|
||||
} fHWBlendState;
|
||||
|
||||
/** IDs for copy surface program. */
|
||||
struct {
|
||||
GrGLuint fProgram;
|
||||
GrGLint fTextureUniform;
|
||||
GrGLint fTexCoordXformUniform;
|
||||
GrGLint fPosXformUniform;
|
||||
GrGLuint fArrayBuffer;
|
||||
} fCopyProgram;
|
||||
|
||||
TriState fMSAAEnabled;
|
||||
|
||||
GrStencilSettings fHWStencilSettings;
|
||||
|
@ -90,7 +90,7 @@ int GrGLGpu::ProgramCache::search(const GrProgramDesc& desc) const {
|
||||
return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less);
|
||||
}
|
||||
|
||||
GrGLProgram* GrGLGpu::ProgramCache::getProgram(const DrawArgs& args) {
|
||||
GrGLProgram* GrGLGpu::ProgramCache::refProgram(const DrawArgs& args) {
|
||||
#ifdef PROGRAM_CACHE_STATS
|
||||
++fTotalRequests;
|
||||
#endif
|
||||
@ -193,5 +193,5 @@ GrGLProgram* GrGLGpu::ProgramCache::getProgram(const DrawArgs& args) {
|
||||
}
|
||||
}
|
||||
++fCurrLRUStamp;
|
||||
return entry->fProgram;
|
||||
return SkRef(entry->fProgram.get());
|
||||
}
|
||||
|
@ -91,6 +91,25 @@ const char* GrGetGLSLVersionDecl(const GrGLContextInfo& info) {
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLSLAppendDefaultFloatPrecisionDeclaration(GrSLPrecision p, GrGLStandard s, SkString* out) {
|
||||
// Desktop GLSL has added precision qualifiers but they don't do anything.
|
||||
if (kGLES_GrGLStandard == s) {
|
||||
switch (p) {
|
||||
case kHigh_GrSLPrecision:
|
||||
out->append("precision highp float;\n");
|
||||
break;
|
||||
case kMedium_GrSLPrecision:
|
||||
out->append("precision mediump float;\n");
|
||||
break;
|
||||
case kLow_GrSLPrecision:
|
||||
out->append("precision lowp float;\n");
|
||||
break;
|
||||
default:
|
||||
SkFAIL("Unknown precision value.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLSLMulVarBy4f(SkString* outAppend, const char* vec4VarName, const GrGLSLExpr4& mulFactor) {
|
||||
if (mulFactor.isOnes()) {
|
||||
*outAppend = SkString();
|
||||
|
@ -56,6 +56,24 @@ bool GrGetGLSLGeneration(const GrGLInterface* gl, GrGLSLGeneration* generation);
|
||||
*/
|
||||
const char* GrGetGLSLVersionDecl(const GrGLContextInfo&);
|
||||
|
||||
/**
|
||||
* Adds a line of GLSL code to declare the default precision for float types.
|
||||
*/
|
||||
void GrGLSLAppendDefaultFloatPrecisionDeclaration(GrSLPrecision, GrGLStandard, SkString* out);
|
||||
|
||||
/**
|
||||
* Gets the name of the function that should be used to sample a 2D texture. Coord type is used
|
||||
* to indicate whether the texture is sampled using projective textured (kVec3f) or not (kVec2f).
|
||||
*/
|
||||
inline const char* GrGLSLTexture2DFunctionName(GrSLType coordType, GrGLSLGeneration glslGen) {
|
||||
if (kVec2f_GrSLType == coordType) {
|
||||
return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
|
||||
} else {
|
||||
SkASSERT(kVec3f_GrSLType == coordType);
|
||||
return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a GrSLType to a string containing the name of the equivalent GLSL type.
|
||||
*/
|
||||
|
@ -9,9 +9,10 @@
|
||||
#include "GrGLGpu.h"
|
||||
|
||||
|
||||
void GrGLAttribArrayState::set(const GrGLGpu* gpu,
|
||||
|
||||
void GrGLAttribArrayState::set(GrGLGpu* gpu,
|
||||
int index,
|
||||
GrGLVertexBuffer* buffer,
|
||||
GrGLuint vertexBufferID,
|
||||
GrGLint size,
|
||||
GrGLenum type,
|
||||
GrGLboolean normalized,
|
||||
@ -25,13 +26,13 @@ void GrGLAttribArrayState::set(const GrGLGpu* gpu,
|
||||
array->fEnabled = true;
|
||||
}
|
||||
if (!array->fAttribPointerIsValid ||
|
||||
array->fVertexBufferID != buffer->bufferID() ||
|
||||
array->fVertexBufferID != vertexBufferID ||
|
||||
array->fSize != size ||
|
||||
array->fNormalized != normalized ||
|
||||
array->fStride != stride ||
|
||||
array->fOffset != offset) {
|
||||
|
||||
buffer->bind();
|
||||
gpu->bindVertexBuffer(vertexBufferID);
|
||||
GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
|
||||
size,
|
||||
type,
|
||||
@ -39,7 +40,7 @@ void GrGLAttribArrayState::set(const GrGLGpu* gpu,
|
||||
stride,
|
||||
offset));
|
||||
array->fAttribPointerIsValid = true;
|
||||
array->fVertexBufferID = buffer->bufferID();
|
||||
array->fVertexBufferID = vertexBufferID;
|
||||
array->fSize = size;
|
||||
array->fNormalized = normalized;
|
||||
array->fStride = stride;
|
||||
@ -80,15 +81,13 @@ GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
|
||||
return &fAttribArrays;
|
||||
}
|
||||
|
||||
GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu,
|
||||
const GrGLIndexBuffer* buffer) {
|
||||
GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, GrGLuint ibufferID) {
|
||||
GrGLAttribArrayState* state = this->bind(gpu);
|
||||
if (state && buffer) {
|
||||
GrGLuint bufferID = buffer->bufferID();
|
||||
if (!fIndexBufferIDIsValid || bufferID != fIndexBufferID) {
|
||||
GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, bufferID));
|
||||
if (state) {
|
||||
if (!fIndexBufferIDIsValid || ibufferID != fIndexBufferID) {
|
||||
GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibufferID));
|
||||
fIndexBufferIDIsValid = true;
|
||||
fIndexBufferID = bufferID;
|
||||
fIndexBufferID = ibufferID;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
|
@ -67,9 +67,9 @@ public:
|
||||
* assumed that the GrGLAttribArrayState is tracking the state of the currently bound vertex
|
||||
* array object.
|
||||
*/
|
||||
void set(const GrGLGpu*,
|
||||
int index,
|
||||
GrGLVertexBuffer*,
|
||||
void set(GrGLGpu*,
|
||||
int attribIndex,
|
||||
GrGLuint vertexBufferID,
|
||||
GrGLint size,
|
||||
GrGLenum type,
|
||||
GrGLboolean normalized,
|
||||
@ -147,7 +147,7 @@ public:
|
||||
* This is a version of the above function that also binds an index buffer to the vertex
|
||||
* array object.
|
||||
*/
|
||||
GrGLAttribArrayState* bindWithIndexBuffer(GrGLGpu* gpu, const GrGLIndexBuffer*);
|
||||
GrGLAttribArrayState* bindWithIndexBuffer(GrGLGpu* gpu, GrGLuint indexBufferID);
|
||||
|
||||
void notifyIndexBufferDelete(GrGLuint bufferID);
|
||||
|
||||
|
@ -15,26 +15,6 @@
|
||||
const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor";
|
||||
static const char* declared_color_output_name() { return "fsColorOut"; }
|
||||
static const char* dual_source_output_name() { return "dualSourceOut"; }
|
||||
static void append_default_precision_qualifier(GrSLPrecision p,
|
||||
GrGLStandard standard,
|
||||
SkString* str) {
|
||||
// Desktop GLSL has added precision qualifiers but they don't do anything.
|
||||
if (kGLES_GrGLStandard == standard) {
|
||||
switch (p) {
|
||||
case kHigh_GrSLPrecision:
|
||||
str->append("precision highp float;\n");
|
||||
break;
|
||||
case kMedium_GrSLPrecision:
|
||||
str->append("precision mediump float;\n");
|
||||
break;
|
||||
case kLow_GrSLPrecision:
|
||||
str->append("precision lowp float;\n");
|
||||
break;
|
||||
default:
|
||||
SkFAIL("Unknown precision value.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
|
||||
SkASSERT(GrBlendEquationIsAdvanced(equation));
|
||||
@ -270,9 +250,9 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
SkTDArray<GrGLuint>* shaderIds) {
|
||||
GrGLGpu* gpu = fProgramBuilder->gpu();
|
||||
this->versionDecl() = GrGetGLSLVersionDecl(gpu->ctxInfo());
|
||||
append_default_precision_qualifier(kDefault_GrSLPrecision,
|
||||
gpu->glStandard(),
|
||||
&this->precisionQualifier());
|
||||
GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
|
||||
gpu->glStandard(),
|
||||
&this->precisionQualifier());
|
||||
this->compileAndAppendLayoutQualifiers();
|
||||
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility,
|
||||
&this->uniforms());
|
||||
|
@ -343,8 +343,7 @@ void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
|
||||
fFS.enableSecondaryOutput();
|
||||
}
|
||||
|
||||
// On any post 1.10 GLSL supporting GPU, we declare custom output
|
||||
if (k110_GrGLSLGeneration != fFS.fProgramBuilder->gpu()->glslGeneration()) {
|
||||
if (this->ctxInfo().caps()->glslCaps()->mustDeclareFragmentShaderOutput()) {
|
||||
fFS.enableCustomOutput();
|
||||
}
|
||||
|
||||
|
@ -12,14 +12,6 @@
|
||||
#include "../GrGLShaderVar.h"
|
||||
|
||||
namespace {
|
||||
inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
|
||||
if (kVec2f_GrSLType == type) {
|
||||
return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
|
||||
} else {
|
||||
SkASSERT(kVec3f_GrSLType == type);
|
||||
return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
|
||||
}
|
||||
}
|
||||
void append_texture_lookup(SkString* out,
|
||||
GrGLGpu* gpu,
|
||||
const char* samplerName,
|
||||
@ -30,7 +22,7 @@ void append_texture_lookup(SkString* out,
|
||||
SkASSERT(coordName);
|
||||
|
||||
out->appendf("%s(%s, %s)",
|
||||
sample_function_name(varyingType, gpu->glslGeneration()),
|
||||
GrGLSLTexture2DFunctionName(varyingType, gpu->glslGeneration()),
|
||||
samplerName,
|
||||
coordName);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user