static void RunBuilderTest(skiatest::Reporter* reporter, SkTextBlobBuilder& builder, const RunDef in[], unsigned inCount, const RunDef out[], unsigned outCount) { SkFont font; unsigned glyphCount = 0; unsigned posCount = 0; for (unsigned i = 0; i < inCount; ++i) { AddRun(font, in[i].count, in[i].pos, SkPoint::Make(in[i].x, in[i].y), builder); glyphCount += in[i].count; posCount += in[i].count * in[i].pos; } sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, (inCount > 0) == SkToBool(blob)); if (!blob) { return; } SkTextBlobRunIterator it(blob.get()); for (unsigned i = 0; i < outCount; ++i) { REPORTER_ASSERT(reporter, !it.done()); REPORTER_ASSERT(reporter, out[i].pos == it.positioning()); REPORTER_ASSERT(reporter, out[i].count == it.glyphCount()); if (SkTextBlobRunIterator::kDefault_Positioning == out[i].pos) { REPORTER_ASSERT(reporter, out[i].x == it.offset().x()); REPORTER_ASSERT(reporter, out[i].y == it.offset().y()); } else if (SkTextBlobRunIterator::kHorizontal_Positioning == out[i].pos) { REPORTER_ASSERT(reporter, out[i].y == it.offset().y()); } for (unsigned k = 0; k < it.glyphCount(); ++k) { REPORTER_ASSERT(reporter, k % 128 == it.glyphs()[k]); if (SkTextBlobRunIterator::kHorizontal_Positioning == it.positioning()) { REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k]); } else if (SkTextBlobRunIterator::kFull_Positioning == it.positioning()) { REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k * 2]); REPORTER_ASSERT(reporter, -SkIntToScalar(k % 128) == it.pos()[k * 2 + 1]); } } it.next(); } REPORTER_ASSERT(reporter, it.done()); }
bool SkDisplayBounds::draw(SkAnimateMaker& maker) { maker.fDisplayList.fUnionBounds = SkToBool(inval); maker.fDisplayList.fDrawBounds = false; fBounds.setEmpty(); bool result = INHERITED::draw(maker); maker.fDisplayList.fUnionBounds = false; maker.fDisplayList.fDrawBounds = true; if (inval && fBounds.isEmpty() == false) { SkIRect& rect = maker.fDisplayList.fInvalBounds; maker.fDisplayList.fHasUnion = true; if (rect.isEmpty()) rect = fBounds; else rect.join(fBounds); } return result; }
void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelineBuilder, GrXferProcessor::OptFlags flags, const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, int* firstColorProcessorIdx, int* firstCoverageProcessorIdx) { fIgnoresCoverage = SkToBool(flags & GrXferProcessor::kIgnoreCoverage_OptFlag); if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) || (flags & GrXferProcessor::kOverrideColor_OptFlag)) { *firstColorProcessorIdx = pipelineBuilder.numColorFragmentProcessors(); } if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) { *firstCoverageProcessorIdx = pipelineBuilder.numCoverageFragmentProcessors(); } }
bool sk_isdir(const char *path) { struct stat status; if (0 != stat(path, &status)) { #ifdef SK_BUILD_FOR_IOS // check the bundle directory if not in default path SkString bundlePath; if (ios_get_path_in_bundle(path, &bundlePath)) { if (0 != stat(bundlePath.c_str(), &status)) { return false; } } #else return false; #endif } return SkToBool(status.st_mode & S_IFDIR); }
bool SkHitTestPathEx(const SkPath& path, SkScalar x, SkScalar y) { bool isInverse = path.isInverseFillType(); if (path.isEmpty()) { return isInverse; } const SkRect& bounds = path.getBounds(); if (!bounds.contains(x, y)) { return isInverse; } SkPath::Iter iter(path, true); bool done = false; int w = 0; do { SkPoint pts[4]; switch (iter.next(pts, false)) { case SkPath::kMove_Verb: case SkPath::kClose_Verb: break; case SkPath::kLine_Verb: w += winding_line(pts, x, y); break; case SkPath::kQuad_Verb: w += winding_quad(pts, x, y); break; case SkPath::kCubic_Verb: w += winding_cubic(pts, x, y); break; case SkPath::kDone_Verb: done = true; break; } } while (!done); switch (path.getFillType()) { case SkPath::kEvenOdd_FillType: case SkPath::kInverseEvenOdd_FillType: w &= 1; break; default: break; } return SkToBool(w); }
SkSurface* SkSurface::NewWrappedRenderTarget(GrContext* context, GrBackendTextureDesc desc, const SkSurfaceProps* props) { if (NULL == context) { return NULL; } if (!SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) { return NULL; } SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc)); if (!surface) { return NULL; } SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(surface->asRenderTarget(), props)); if (!device) { return NULL; } return SkNEW_ARGS(SkSurface_Gpu, (device)); }
void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocalStream) const { // Get the family name. SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames; HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames)); UINT32 dwFamilyNamesLength; HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength)); SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1); HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1)); SkString utf8FamilyName; HRV(sk_wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName)); desc->setFamilyName(utf8FamilyName.c_str()); *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); }
static bool draw_path_cell(SkCanvas* canvas, SkImage* img, int expectedCaps) { // Draw the image canvas->drawImage(img, 0, 0); int w = img->width(), h = img->height(); // Read the pixels back SkImageInfo info = SkImageInfo::MakeN32Premul(w, h); SkAutoPixmapStorage pmap; pmap.alloc(info); if (!img->readPixels(pmap, 0, 0)) { return false; } // To account for rasterization differences, we scan the middle two rows [y, y+1] of the image SkASSERT(h % 2 == 0); int y = (h - 1) / 2; bool inBlob = false; int numBlobs = 0; for (int x = 0; x < w; ++x) { // We drew white-on-black. We can look for any non-zero value. Just check red. // And we care if either row is non-zero, so just add them to simplify everything. uint32_t v = SkGetPackedR32(*pmap.addr32(x, y)) + SkGetPackedR32(*pmap.addr32(x, y + 1)); if (!inBlob && v) { ++numBlobs; } inBlob = SkToBool(v); } SkPaint outline; outline.setStyle(SkPaint::kStroke_Style); if (numBlobs == expectedCaps) { outline.setColor(0xFF007F00); // Green } else if (numBlobs > expectedCaps) { outline.setColor(0xFF7F7F00); // Yellow -- more geometry than expected } else { outline.setColor(0xFF7F0000); // Red -- missing some geometry } canvas->drawRect(SkRect::MakeWH(w, h), outline); return numBlobs == expectedCaps; }
bool Window_mac::attach(BackendType attachType) { this->initWindow(); window_context_factory::MacWindowInfo info; info.fWindow = fWindow; switch (attachType) { case kRaster_BackendType: fWindowContext = NewRasterForMac(info, fRequestedDisplayParams); break; case kNativeGL_BackendType: default: fWindowContext = NewGLForMac(info, fRequestedDisplayParams); break; } this->onBackendCreated(); return (SkToBool(fWindowContext)); }
void updateReader() { if (NULL == fReader) { return; } bool crossProcess = SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag); fReader->setFlags(SkSetClearMask(fReader->getFlags(), crossProcess, SkReadBuffer::kCrossProcess_Flag)); if (crossProcess) { fReader->setFactoryArray(&fFactoryArray); } else { fReader->setFactoryArray(NULL); } if (shouldFlattenBitmaps(fFlags)) { fReader->setBitmapStorage(this); } else { fReader->setBitmapStorage(fSharedHeap); } }
GrMorphologyEffect::GrMorphologyEffect(sk_sp<GrTextureProxy> proxy, Direction direction, int radius, Type type, const float range[2]) : INHERITED(kGrMorphologyEffect_ClassID, ModulateByConfigOptimizationFlags(proxy->config())) , fCoordTransform(proxy.get()) , fTextureSampler(std::move(proxy)) , fDirection(direction) , fRadius(radius) , fType(type) , fUseRange(SkToBool(range)) { this->addCoordTransform(&fCoordTransform); this->setTextureSamplerCnt(1); if (fUseRange) { fRange[0] = range[0]; fRange[1] = range[1]; } }
/** * This test contains basic sanity checks concerning bitmaps. */ DEF_TEST(Bitmap, reporter) { // Zero-sized bitmaps are allowed for (int width = 0; width < 2; ++width) { for (int height = 0; height < 2; ++height) { SkBitmap bm; bool setConf = bm.setInfo(SkImageInfo::MakeN32Premul(width, height)); REPORTER_ASSERT(reporter, setConf); if (setConf) { bm.allocPixels(); } REPORTER_ASSERT(reporter, SkToBool(width & height) != bm.empty()); } } test_bigwidth(reporter); test_allocpixels(reporter); test_bigalloc(reporter); test_peekpixels(reporter); }
bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target, int vertexCount, int indexCount) { this->reset(); fTarget = target; bool success = true; if (fTarget) { success = target->reserveVertexAndIndexSpace(vertexCount, indexCount, &fVertices, &fIndices); if (!success) { fTarget = NULL; this->reset(); } } SkASSERT(success == SkToBool(fTarget)); return success; }
void GrVkCaps::initGrCaps(const VkPhysicalDeviceProperties& properties, const VkPhysicalDeviceMemoryProperties& memoryProperties, uint32_t featureFlags) { // So GPUs, like AMD, are reporting MAX_INT support vertex attributes. In general, there is no // need for us ever to support that amount, and it makes tests which tests all the vertex // attribs timeout looping over that many. For now, we'll cap this at 64 max and can raise it if // we ever find that need. static const uint32_t kMaxVertexAttributes = 64; fMaxVertexAttributes = SkTMin(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes); // AMD advertises support for MAX_UINT vertex input attributes, but in reality only supports 32. if (kAMD_VkVendor == properties.vendorID) { fMaxVertexAttributes = SkTMin(fMaxVertexAttributes, 32); } // We could actually query and get a max size for each config, however maxImageDimension2D will // give the minimum max size across all configs. So for simplicity we will use that for now. fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX); fMaxTextureSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX); this->initSampleCount(properties); // Assuming since we will always map in the end to upload the data we might as well just map // from the get go. There is no hard data to suggest this is faster or slower. fBufferMapThreshold = 0; fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag; fOversizedStencilSupport = true; fSampleShadingSupport = SkToBool(featureFlags & kSampleRateShading_GrVkFeatureFlag); // AMD seems to have issues binding new VkPipelines inside a secondary command buffer. // Current workaround is to use a different secondary command buffer for each new VkPipeline. if (kAMD_VkVendor == properties.vendorID) { fNewCBOnPipelineChange = true; } #if defined(SK_CPU_X86) if (kImagination_VkVendor == properties.vendorID) { fSRGBSupport = false; } #endif }
SkSurface* SkSurface::NewFromBackendTexture(GrContext* context, const GrBackendTextureDesc& desc, const SkSurfaceProps* props) { if (NULL == context) { return NULL; } if (!SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) { return NULL; } SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc, kBorrow_GrWrapOwnership)); if (!surface) { return NULL; } SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(surface->asRenderTarget(), props, SkGpuDevice::kUninit_InitContents)); if (!device) { return NULL; } return SkNEW_ARGS(SkSurface_Gpu, (device)); }
bool GrGLProgram::genProgram(const GrCustomStage** customStages) { GrAssert(0 == fProgramID); GrGLShaderBuilder builder(fContextInfo, fUniformManager); const uint32_t& layout = fDesc.fVertexLayout; #if GR_GL_EXPERIMENTAL_GS builder.fUsesGS = fDesc.fExperimentalGS; #endif SkXfermode::Coeff colorCoeff, uniformCoeff; bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled); // The rest of transfer mode color filters have not been implemented if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { GR_DEBUGCODE(bool success =) SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> (fDesc.fColorFilterXfermode), &uniformCoeff, &colorCoeff); GR_DEBUGASSERT(success); } else {
bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* data) const { GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext(); GrContext* ctx = fDevice->context(); int maxResourceCount; size_t maxResourceBytes; ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes); bool mipmapped = rtc->asTextureProxy() ? GrMipMapped::kYes == rtc->asTextureProxy()->mipMapped() : false; data->set(ctx->threadSafeProxy(), maxResourceBytes, rtc->origin(), rtc->width(), rtc->height(), rtc->colorSpaceInfo().config(), rtc->fsaaType(), rtc->numStencilSamples(), SkSurfaceCharacterization::Textureable(SkToBool(rtc->asTextureProxy())), SkSurfaceCharacterization::MipMapped(mipmapped), rtc->colorSpaceInfo().refColorSpace(), this->props()); return true; }
size_t GrTexture::onGpuMemorySize() const { size_t textureSize; if (GrPixelConfigIsCompressed(fDesc.fConfig)) { textureSize = GrCompressedFormatDataSize(fDesc.fConfig, fDesc.fWidth, fDesc.fHeight); } else { textureSize = (size_t) fDesc.fWidth * fDesc.fHeight * GrBytesPerPixel(fDesc.fConfig); } if (this->texturePriv().hasMipMaps()) { // We don't have to worry about the mipmaps being a different size than // we'd expect because we never change fDesc.fWidth/fHeight. textureSize += textureSize/3; } SkASSERT(!SkToBool(fDesc.fFlags & kRenderTarget_GrSurfaceFlag)); SkASSERT(textureSize <= WorseCaseSize(fDesc)); return textureSize; }
void VisualSKPBench::onDraw(int loops, SkCanvas* canvas) { bool isOffset = SkToBool(fCullRect.left() | fCullRect.top()); if (isOffset) { canvas->save(); canvas->translate(SkIntToScalar(-fCullRect.left()), SkIntToScalar(-fCullRect.top())); } for (int i = 0; i < loops; i++) { canvas->drawPicture(fPic); #if SK_SUPPORT_GPU // Ensure the GrContext doesn't batch across draw loops. if (GrContext* context = canvas->getGrContext()) { context->flush(); } #endif } if (isOffset) { canvas->restore(); } }
void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage, const SkTSet<SkPDFObject*>& knownResourceObjects, SkTSet<SkPDFObject*>* newResourceObjects) { if (fContentStream.get() == NULL) { insert("Resources", fDevice->getResourceDict()); SkSafeUnref(this->insert("MediaBox", fDevice->copyMediaBox())); if (!SkToBool(catalog->getDocumentFlags() & SkPDFDocument::kNoLinks_Flags)) { SkPDFArray* annots = fDevice->getAnnotations(); if (annots && annots->size() > 0) { insert("Annots", annots); } } SkAutoTUnref<SkStream> content(fDevice->content()); fContentStream.reset(new SkPDFStream(content.get())); insert("Contents", new SkPDFObjRef(fContentStream.get()))->unref(); } catalog->addObject(fContentStream.get(), firstPage); fDevice->getResources(knownResourceObjects, newResourceObjects, true); }
void GrVkCaps::initGrCaps(const VkPhysicalDeviceProperties& properties, const VkPhysicalDeviceMemoryProperties& memoryProperties, uint32_t featureFlags) { fMaxVertexAttributes = properties.limits.maxVertexInputAttributes; // We could actually query and get a max size for each config, however maxImageDimension2D will // give the minimum max size across all configs. So for simplicity we will use that for now. fMaxRenderTargetSize = properties.limits.maxImageDimension2D; fMaxTextureSize = properties.limits.maxImageDimension2D; this->initSampleCount(properties); // Assuming since we will always map in the end to upload the data we might as well just map // from the get go. There is no hard data to suggest this is faster or slower. fBufferMapThreshold = 0; fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag; fStencilWrapOpsSupport = true; fOversizedStencilSupport = true; fSampleShadingSupport = SkToBool(featureFlags & kSampleRateShading_GrVkFeatureFlag); }
Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPaint& paint) { Resources resources(paint); // FIXME: this is a weak heuristic and we end up with LOTS of redundant clips. bool hasClip = !draw.fClipStack->isWideOpen(); bool hasShader = SkToBool(paint.getShader()); if (hasClip || hasShader) { AutoElement defs("defs", fWriter); if (hasClip) { this->addClipResources(draw, &resources); } if (hasShader) { this->addShaderResources(paint, &resources); } } return resources; }
DEF_TEST(ImageDecoding_alphaType, reporter) { SkString resourcePath = GetResourcePath(); if (resourcePath.isEmpty()) { SkDebugf("Could not run alphaType test because resourcePath not specified."); return; } SkOSFile::Iter iter(resourcePath.c_str()); SkString basename; if (iter.next(&basename)) { do { SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(), basename.c_str()); for (int truth = 0; truth <= 1; ++truth) { test_alphaType(reporter, filename, SkToBool(truth)); } } while (iter.next(&basename)); } else { SkDebugf("Failed to find any files :(\n"); } }
void GrDrawTarget::stencilPath(GrDrawContext* drawContext, const GrClip& clip, const GrUserStencilSettings* ss, bool useHWAA, const SkMatrix& viewMatrix, const GrPath* path) { // TODO: extract portions of checkDraw that are relevant to path stenciling. SkASSERT(path); SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport()); // Setup clip GrAppliedClip appliedClip; if (!clip.apply(fContext, drawContext, nullptr, useHWAA, SkToBool(ss), &appliedClip)) { return; } // TODO: respect fClipBatchToBounds if we ever start computing bounds here. // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never // attempt this in a situation that would require coverage AA. SkASSERT(!appliedClip.getClipCoverageFragmentProcessor()); GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment( drawContext->accessRenderTarget()); if (!stencilAttachment) { SkDebugf("ERROR creating stencil attachment. Draw skipped.\n"); return; } GrBatch* batch = GrStencilPathBatch::Create(viewMatrix, useHWAA, path->getFillType(), appliedClip.hasStencilClip(), stencilAttachment->bits(), appliedClip.scissorState(), drawContext->accessRenderTarget(), path); this->recordBatch(batch, appliedClip.deviceBounds()); batch->unref(); }
void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage, SkTDArray<SkPDFObject*>* resourceObjects) { if (fContentStream.get() == NULL) { insert("Resources", fDevice->getResourceDict()); insert("MediaBox", fDevice->getMediaBox().get()); if (!SkToBool(catalog->getDocumentFlags() & SkPDFDocument::kNoLinks_Flags)) { SkRefPtr<SkPDFArray> annots = fDevice->getAnnotations(); if (annots.get() && annots->size() > 0) { insert("Annots", annots.get()); } } SkRefPtr<SkStream> content = fDevice->content(); content->unref(); // SkRefPtr and content() both took a reference. fContentStream = new SkPDFStream(content.get()); fContentStream->unref(); // SkRefPtr and new both took a reference. insert("Contents", new SkPDFObjRef(fContentStream.get()))->unref(); } catalog->addObject(fContentStream.get(), firstPage); fDevice->getResources(resourceObjects, true); }
bool Window_mac::attach(BackendType attachType, const DisplayParams& params) { this->initWindow(fDisplay, ¶ms); MacWindowInfo info; #if 0 // Init Mac window info here info.foo = foo; #endif switch (attachType) { #ifdef SK_VULKAN case kVulkan_BackendType: fWindowContext = NewVulkanForMac(info, params); break; #endif case kNativeGL_BackendType: default: fWindowContext = NewGLForMac(info, params); break; } return (SkToBool(fWindowContext)); }
void drawContent(SkCanvas* canvas) { canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); SkPaint paint; sk_tool_utils::set_portable_typeface(&paint); paint.setColor(0x80F60000); const Proc procs[] = { draw_hair, draw_thick, draw_rect, draw_oval, draw_text }; const SkXfermode::Mode modes[] = { SkXfermode::kSrcOver_Mode, SkXfermode::kSrc_Mode, SkXfermode::kClear_Mode }; const PaintProc paintProcs[] = { identity_paintproc, gradient_paintproc }; for (int aa = 0; aa <= 1; ++aa) { paint.setAntiAlias(SkToBool(aa)); canvas->save(); for (size_t i = 0; i < SK_ARRAY_COUNT(paintProcs); ++i) { paintProcs[i](&paint); for (size_t x = 0; x < SK_ARRAY_COUNT(modes); ++x) { paint.setXfermodeMode(modes[x]); canvas->save(); for (size_t y = 0; y < SK_ARRAY_COUNT(procs); ++y) { procs[y](canvas, paint); canvas->translate(0, H * 5 / 4); } canvas->restore(); canvas->translate(W * 5 / 4, 0); } } canvas->restore(); canvas->translate(0, (H * 5 / 4) * SK_ARRAY_COUNT(procs)); } }
SkDrawable* SkPictureRecorder::endRecordingAsDrawable() { fActivelyRecording = false; fRecorder->flushMiniRecorder(); fRecorder->restoreToCount(1); // If we were missing any restores, add them now. // TODO: delay as much of this work until just before first playback? SkRecordOptimize(fRecord); if (fBBH.get()) { SkRecordFillBounds(fCullRect, *fRecord, fBBH.get()); } SkDrawable* drawable = new SkRecordedDrawable(fRecord, fBBH, fRecorder->detachDrawableList(), fCullRect, SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag)); // release our refs now, so only the drawable will be the owner. fRecord.reset(NULL); fBBH.reset(NULL); return drawable; }
bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height, GrPixelConfig srcConfig, DrawPreference* drawPreference, WritePixelTempDrawInfo* tempDrawInfo) { SkASSERT(drawPreference); SkASSERT(tempDrawInfo); SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference); if (GrPixelConfigIsCompressed(dstSurface->desc().fConfig) && dstSurface->desc().fConfig != srcConfig) { return false; } if (SkToBool(dstSurface->asRenderTarget())) { if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) { ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() && (width < dstSurface->width() || height < dstSurface->height())) { ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); } } if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference, tempDrawInfo)) { return false; } // Check to see if we're going to request that the caller draw when drawing is not possible. if (!dstSurface->asRenderTarget() || !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) { // If we don't have a fallback to a straight upload then fail. if (kRequireDraw_DrawPreference == *drawPreference || !this->caps()->isConfigTexturable(srcConfig)) { return false; } *drawPreference = kNoDraw_DrawPreference; } return true; }
GrTexture* GrGpu::createTexture(const GrSurfaceDesc& desc, bool budgeted, const void* srcData, size_t rowBytes) { if (!this->caps()->isConfigTexturable(desc.fConfig)) { return NULL; } bool isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); if (isRT && !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) { return NULL; } GrTexture *tex = NULL; if (GrPixelConfigIsCompressed(desc.fConfig)) { // We shouldn't be rendering into this SkASSERT((desc.fFlags & kRenderTarget_GrSurfaceFlag) == 0); if (!this->caps()->npotTextureTileSupport() && (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) { return NULL; } this->handleDirtyContext(); tex = this->onCreateCompressedTexture(desc, budgeted, srcData); } else { this->handleDirtyContext(); tex = this->onCreateTexture(desc, budgeted, srcData, rowBytes); } if (!this->caps()->reuseScratchTextures() && !isRT) { tex->resourcePriv().removeScratchKey(); } if (tex) { fStats.incTextureCreates(); if (srcData) { fStats.incTextureUploads(); } } return tex; }