bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf, GrGLenum format, GrGLenum type) const { if (GR_GL_RGBA == format && GR_GL_UNSIGNED_BYTE == type) { // ES 2 guarantees this format is supported return true; } if (!fTwoFormatLimit) { // not limited by ES 2's constraints return true; } GrGLint otherFormat = GR_GL_RGBA; GrGLint otherType = GR_GL_UNSIGNED_BYTE; // The other supported format/type combo supported for ReadPixels // can change based on which render target is bound GR_GL_GetIntegerv(intf, GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &otherFormat); GR_GL_GetIntegerv(intf, GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &otherType); return (GrGLenum)otherFormat == format && (GrGLenum)otherType == type; }
GrBackendRenderTargetDesc SkGLWidget::getDesc(int w, int h) { GrBackendRenderTargetDesc desc; desc.fWidth = SkScalarRoundToInt(this->width()); desc.fHeight = SkScalarRoundToInt(this->height()); desc.fConfig = kSkia8888_GrPixelConfig; GR_GL_GetIntegerv(fCurIntf, GR_GL_SAMPLES, &desc.fSampleCnt); GR_GL_GetIntegerv(fCurIntf, GR_GL_STENCIL_BITS, &desc.fStencilBits); GrGLint buffer; GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer); desc.fRenderTargetHandle = buffer; return desc; }
void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo) { fMSFBOType = kNone_MSFBOType; if (kDesktop_GrGLBinding != ctxInfo.binding()) { if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) { // chrome's extension is equivalent to the EXT msaa // and fbo_blit extensions. fMSFBOType = kDesktopEXT_MSFBOType; } else if (ctxInfo.hasExtension("GL_APPLE_framebuffer_multisample")) { fMSFBOType = kAppleES_MSFBOType; } } else { if ((ctxInfo.version() >= GR_GL_VER(3,0)) || ctxInfo.hasExtension("GL_ARB_framebuffer_object")) { fMSFBOType = GrGLCaps::kDesktopARB_MSFBOType; } else if (ctxInfo.hasExtension("GL_EXT_framebuffer_multisample") && ctxInfo.hasExtension("GL_EXT_framebuffer_blit")) { fMSFBOType = GrGLCaps::kDesktopEXT_MSFBOType; } // TODO: We could populate fMSAACoverageModes using GetInternalformativ // on GL 4.2+. It's format-specific, though. See also // http://code.google.com/p/skia/issues/detail?id=470 about using actual // rather than requested sample counts in cache key. if (ctxInfo.hasExtension("GL_NV_framebuffer_multisample_coverage")) { fCoverageAAType = kNVDesktop_CoverageAAType; GrGLint count; GR_GL_GetIntegerv(ctxInfo.interface(), GR_GL_MAX_MULTISAMPLE_COVERAGE_MODES, &count); fMSAACoverageModes.setCount(count); GR_GL_GetIntegerv(ctxInfo.interface(), GR_GL_MULTISAMPLE_COVERAGE_MODES, (int*)&fMSAACoverageModes[0]); // The NV driver seems to return the modes already sorted but the // spec doesn't require this. So we sort. SkQSortCompareProc compareProc = reinterpret_cast<SkQSortCompareProc>(&coverage_mode_compare); SkQSort(&fMSAACoverageModes[0], count, sizeof(MSAACoverageMode), compareProc); } } if (kNone_MSFBOType != fMSFBOType) { GR_GL_GetIntegerv(ctxInfo.interface(), GR_GL_MAX_SAMPLES, &fMaxSampleCount); } }
GrGpuGLShaders::GrGpuGLShaders(const GrGLContextInfo& ctxInfo) : GrGpuGL(ctxInfo) { // Enable supported shader-related caps if (kDesktop_GrGLBinding == this->glBinding()) { fCaps.fDualSourceBlendingSupport = this->glVersion() >= GR_GL_VER(3,3) || this->hasExtension("GL_ARB_blend_func_extended"); fCaps.fShaderDerivativeSupport = true; // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS fCaps.fGeometryShaderSupport = this->glVersion() >= GR_GL_VER(3,2) && this->glslGeneration() >= k150_GrGLSLGeneration; } else { fCaps.fShaderDerivativeSupport = this->hasExtension("GL_OES_standard_derivatives"); } GR_GL_GetIntegerv(this->glInterface(), GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttribs); fProgramData = NULL; fProgramCache = new ProgramCache(this->glContextInfo()); #if 0 this->programUnitTest(); #endif }
GrGpuGLShaders::GrGpuGLShaders(const GrGLInterface* gl) : GrGpuGL(gl, get_binding_in_use(gl)) { GrGLSLGeneration glslGeneration = GetGLSLGeneration(this->glBinding(), gl); // Enable supported shader-releated caps fCaps.fShaderSupport = true; fCaps.fSupportPerVertexCoverage = true; if (kDesktop_GrGLBinding == this->glBinding()) { fCaps.fDualSourceBlendingSupport = this->glVersion() >= GR_GL_VER(3,3) || this->hasExtension("GL_ARB_blend_func_extended"); fCaps.fShaderDerivativeSupport = true; // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS fCaps.fGeometryShaderSupport = this->glVersion() >= GR_GL_VER(3,2) && glslGeneration >= k150_GLSLGeneration; } else { fCaps.fShaderDerivativeSupport = this->hasExtension("GL_OES_standard_derivatives"); } GR_GL_GetIntegerv(gl, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttribs); fProgramData = NULL; fProgramCache = new ProgramCache(gl, glslGeneration); #if 0 this->programUnitTest(); #endif }
void SkV8ExampleWindow::windowSizeChanged() { if (FLAGS_gpu) { SkOSWindow::AttachmentInfo attachmentInfo; bool result = this->attach( SkOSWindow::kNativeGL_BackEndType, 0, false, &attachmentInfo); if (!result) { printf("Failed to attach."); exit(1); } fCurIntf = GrGLCreateNativeInterface(); fCurContext = GrContext::Create( kOpenGL_GrBackend, (GrBackendContext) fCurIntf); if (NULL == fCurIntf || NULL == fCurContext) { printf("Failed to initialize GL."); exit(1); } GrBackendRenderTargetDesc desc; desc.fWidth = SkScalarRoundToInt(this->width()); desc.fHeight = SkScalarRoundToInt(this->height()); desc.fConfig = kSkia8888_GrPixelConfig; desc.fOrigin = kBottomLeft_GrSurfaceOrigin; desc.fSampleCnt = attachmentInfo.fSampleCount; desc.fStencilBits = attachmentInfo.fStencilBits; GrGLint buffer; GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer); desc.fRenderTargetHandle = buffer; SkSafeUnref(fCurSurface); fCurSurface = SkSurface::MakeFromBackendRenderTarget(fCurContext, desc, nullptr, nullptr).release(); } }
sk_sp<SkSurface> SkSurface_Compute::MakeComputeBackedSurface(SkWindow * const window, const SkWindow::AttachmentInfo & attachmentInfo, GrGLInterface const * const grInterface, GrContext * const grContext, sk_sp<SkContext_Compute> compute) { GrBackendRenderTargetDesc desc; desc.fWidth = SkScalarRoundToInt(window->width()); desc.fHeight = SkScalarRoundToInt(window->height()); if (0 == desc.fWidth || 0 == desc.fHeight) { return nullptr; } // TODO: Query the actual framebuffer for sRGB capable. However, to // preserve old (fake-linear) behavior, we don't do this. Instead, rely // on the flag (currently driven via 'C' mode in SampleApp). // // Also, we may not have real sRGB support (ANGLE, in particular), so check for // that, and fall back to L32: // // ... and, if we're using a 10-bit/channel FB0, it doesn't do sRGB conversion on write, // so pretend that it's non-sRGB 8888: desc.fConfig = grContext->caps()->srgbSupport() && SkImageInfoIsGammaCorrect(window->info()) && (attachmentInfo.fColorBits != 30) ? kSkiaGamma8888_GrPixelConfig : kSkia8888_GrPixelConfig; desc.fOrigin = kBottomLeft_GrSurfaceOrigin; desc.fSampleCnt = 0; // attachmentInfo.fSampleCount; desc.fStencilBits = 0; // attachmentInfo.fStencilBits; GrGLint buffer; GR_GL_GetIntegerv(grInterface,GR_GL_FRAMEBUFFER_BINDING,&buffer); desc.fRenderTargetHandle = buffer; sk_sp<SkColorSpace> colorSpace = grContext->caps()->srgbSupport() && SkImageInfoIsGammaCorrect(window->info()) ? SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) : nullptr; // // // if (!grContext) { return nullptr; } if (!SkSurface_Gpu::Valid(grContext,desc.fConfig,colorSpace.get())) { return nullptr; } return sk_make_sp<SkSurface_Compute>(compute,desc.fWidth,desc.fHeight); }
GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo, const GrGLInterface* interface, GrContext* grContext) { GrBackendRenderTargetDesc desc; desc.fWidth = SkScalarRoundToInt(this->width()); desc.fHeight = SkScalarRoundToInt(this->height()); desc.fConfig = kSkia8888_GrPixelConfig; desc.fOrigin = kBottomLeft_GrSurfaceOrigin; desc.fSampleCnt = attachmentInfo.fSampleCount; desc.fStencilBits = attachmentInfo.fStencilBits; GrGLint buffer; GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer); desc.fRenderTargetHandle = buffer; return grContext->textureProvider()->wrapBackendRenderTarget(desc); }
void SkExampleWindow::setupRenderTarget() { GrBackendRenderTargetDesc desc; desc.fWidth = SkScalarRoundToInt(width()); desc.fHeight = SkScalarRoundToInt(height()); desc.fConfig = kSkia8888_GrPixelConfig; desc.fOrigin = kBottomLeft_GrSurfaceOrigin; desc.fSampleCnt = fAttachmentInfo.fSampleCount; desc.fStencilBits = fAttachmentInfo.fStencilBits; GrGLint buffer; GR_GL_GetIntegerv(fInterface, GR_GL_FRAMEBUFFER_BINDING, &buffer); desc.fRenderTargetHandle = buffer; fRenderTarget = fContext->wrapBackendRenderTarget(desc); fContext->setRenderTarget(fRenderTarget); }
GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo, const GrGLInterface* interface, GrContext* grContext) { GrBackendRenderTargetDesc desc; desc.fWidth = SkScalarRoundToInt(this->width()); desc.fHeight = SkScalarRoundToInt(this->height()); // TODO: Query the actual framebuffer for sRGB capable. However, to // preserve old (fake-linear) behavior, we don't do this. Instead, rely // on the flag (currently driven via 'C' mode in SampleApp). // // Also, we may not have real sRGB support (ANGLE, in particular), so check for // that, and fall back to L32: desc.fConfig = grContext->caps()->srgbSupport() && SkImageInfoIsGammaCorrect(info()) ? kSkiaGamma8888_GrPixelConfig : kSkia8888_GrPixelConfig; desc.fOrigin = kBottomLeft_GrSurfaceOrigin; desc.fSampleCnt = attachmentInfo.fSampleCount; desc.fStencilBits = attachmentInfo.fStencilBits; GrGLint buffer; GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer); desc.fRenderTargetHandle = buffer; return grContext->textureProvider()->wrapBackendRenderTarget(desc); }
void GrGLCaps::init(const GrGLContextInfo& ctxInfo) { this->reset(); if (!ctxInfo.isInitialized()) { return; } const GrGLInterface* gli = ctxInfo.interface(); GrGLBinding binding = ctxInfo.binding(); GrGLVersion version = ctxInfo.version(); if (kES2_GrGLBinding == binding) { GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &fMaxFragmentUniformVectors); } else { GrAssert(kDesktop_GrGLBinding == binding); GrGLint max; GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max); fMaxFragmentUniformVectors = max / 4; } if (kDesktop_GrGLBinding == binding) { fRGBA8RenderbufferSupport = true; } else { fRGBA8RenderbufferSupport = ctxInfo.hasExtension("GL_OES_rgb8_rgba8") || ctxInfo.hasExtension("GL_ARM_rgba8"); } if (kDesktop_GrGLBinding == binding) { fBGRAFormatSupport = version >= GR_GL_VER(1,2) || ctxInfo.hasExtension("GL_EXT_bgra"); } else { bool hasBGRAExt = false; if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { fBGRAFormatSupport = true; } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { fBGRAFormatSupport = true; fBGRAIsInternalFormat = true; } GrAssert(fBGRAFormatSupport || kSkia8888_PM_GrPixelConfig != kBGRA_8888_PM_GrPixelConfig); } if (kDesktop_GrGLBinding == binding) { fTextureSwizzleSupport = version >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_texture_swizzle"); } else { fTextureSwizzleSupport = false; } if (kDesktop_GrGLBinding == binding) { fUnpackRowLengthSupport = true; fUnpackFlipYSupport = false; fPackRowLengthSupport = true; fPackFlipYSupport = false; } else { fUnpackRowLengthSupport =ctxInfo.hasExtension("GL_EXT_unpack_subimage"); fUnpackFlipYSupport = ctxInfo.hasExtension("GL_CHROMIUM_flipy"); // no extension for pack row length fPackRowLengthSupport = false; fPackFlipYSupport = ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order"); } fTextureUsageSupport = (kES2_GrGLBinding == binding) && ctxInfo.hasExtension("GL_ANGLE_texture_usage"); // Tex storage is in desktop 4.2 and can be an extension to desktop or ES. fTexStorageSupport = (kDesktop_GrGLBinding == binding && version >= GR_GL_VER(4,2)) || ctxInfo.hasExtension("GL_ARB_texture_storage") || ctxInfo.hasExtension("GL_EXT_texture_storage"); // ARB_texture_rg is part of OpenGL 3.0 if (kDesktop_GrGLBinding == binding) { fTextureRedSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_ARB_texture_rg"); } else { fTextureRedSupport = ctxInfo.hasExtension("GL_ARB_texture_rg"); } this->initFSAASupport(ctxInfo); this->initStencilFormats(ctxInfo); }
bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { this->reset(); if (!ctxInfo.isInitialized()) { return false; } GrGLStandard standard = ctxInfo.standard(); GrGLVersion version = ctxInfo.version(); /************************************************************************** * Caps specific to GrGLCaps **************************************************************************/ if (kGLES_GrGLStandard == standard) { GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &fMaxFragmentUniformVectors); } else { SkASSERT(kGL_GrGLStandard == standard); GrGLint max; GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max); fMaxFragmentUniformVectors = max / 4; if (version >= GR_GL_VER(3, 2)) { GrGLint profileMask; GR_GL_GetIntegerv(gli, GR_GL_CONTEXT_PROFILE_MASK, &profileMask); fIsCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT); } if (!fIsCoreProfile) { GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_COORDS, &fMaxFixedFunctionTextureCoords); // Sanity check SkASSERT(fMaxFixedFunctionTextureCoords > 0 && fMaxFixedFunctionTextureCoords < 128); } } GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes); GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &fMaxFragmentTextureUnits); if (kGL_GrGLStandard == standard) { fRGBA8RenderbufferSupport = true; } else { fRGBA8RenderbufferSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_OES_rgb8_rgba8") || ctxInfo.hasExtension("GL_ARM_rgba8"); } if (kGL_GrGLStandard == standard) { fTextureSwizzleSupport = version >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_texture_swizzle"); } else { fTextureSwizzleSupport = version >= GR_GL_VER(3,0); } if (kGL_GrGLStandard == standard) { fUnpackRowLengthSupport = true; fUnpackFlipYSupport = false; fPackRowLengthSupport = true; fPackFlipYSupport = false; } else { fUnpackRowLengthSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_unpack_subimage"); fUnpackFlipYSupport = ctxInfo.hasExtension("GL_CHROMIUM_flipy"); fPackRowLengthSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_NV_pack_subimage"); fPackFlipYSupport = ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order"); } fTextureUsageSupport = (kGLES_GrGLStandard == standard) && ctxInfo.hasExtension("GL_ANGLE_texture_usage"); if (kGL_GrGLStandard == standard) { // The EXT version can apply to either GL or GLES. fTexStorageSupport = version >= GR_GL_VER(4,2) || ctxInfo.hasExtension("GL_ARB_texture_storage") || ctxInfo.hasExtension("GL_EXT_texture_storage"); } else { // Qualcomm Adreno drivers appear to have issues with texture storage. fTexStorageSupport = (version >= GR_GL_VER(3,0) && kQualcomm_GrGLVendor != ctxInfo.vendor()) || ctxInfo.hasExtension("GL_EXT_texture_storage"); } // ARB_texture_rg is part of OpenGL 3.0, but mesa doesn't support it if // it doesn't have ARB_texture_rg extension. if (kGL_GrGLStandard == standard) { if (ctxInfo.isMesa()) { fTextureRedSupport = ctxInfo.hasExtension("GL_ARB_texture_rg"); } else { fTextureRedSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_ARB_texture_rg"); } } else { fTextureRedSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_texture_rg"); } fImagingSupport = kGL_GrGLStandard == standard && ctxInfo.hasExtension("GL_ARB_imaging"); // ES 2 only guarantees RGBA/uchar + one other format/type combo for // ReadPixels. The other format has to checked at run-time since it // can change based on which render target is bound fTwoFormatLimit = kGLES_GrGLStandard == standard; // Known issue on at least some Intel platforms: // http://code.google.com/p/skia/issues/detail?id=946 if (kIntel_GrGLVendor != ctxInfo.vendor()) { fFragCoordsConventionSupport = ctxInfo.glslGeneration() >= k150_GrGLSLGeneration || ctxInfo.hasExtension("GL_ARB_fragment_coord_conventions"); } // SGX and Mali GPUs that are based on a tiled-deferred architecture that have trouble with // frequently changing VBOs. We've measured a performance increase using non-VBO vertex // data for dynamic content on these GPUs. Perhaps we should read the renderer string and // limit this decision to specific GPU families rather than basing it on the vendor alone. if (!GR_GL_MUST_USE_VBO && (kARM_GrGLVendor == ctxInfo.vendor() || kImagination_GrGLVendor == ctxInfo.vendor())) { fUseNonVBOVertexAndIndexDynamicData = true; } if ((kGL_GrGLStandard == standard && version >= GR_GL_VER(4,3)) || (kGLES_GrGLStandard == standard && version >= GR_GL_VER(3,0)) || ctxInfo.hasExtension("GL_ARB_invalidate_subdata")) { fDiscardRenderTargetSupport = true; fInvalidateFBType = kInvalidate_InvalidateFBType; } else if (ctxInfo.hasExtension("GL_EXT_discard_framebuffer")) { fDiscardRenderTargetSupport = true; fInvalidateFBType = kDiscard_InvalidateFBType; } if (kARM_GrGLVendor == ctxInfo.vendor() || kImagination_GrGLVendor == ctxInfo.vendor()) { fFullClearIsFree = true; } if (kGL_GrGLStandard == standard) { fVertexArrayObjectSupport = version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_ARB_vertex_array_object"); } else { fVertexArrayObjectSupport = version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_OES_vertex_array_object"); } if (kGLES_GrGLStandard == standard) { if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) { fFBFetchType = kEXT_FBFetchType; } else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) { fFBFetchType = kNV_FBFetchType; } } // Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor(); this->initFSAASupport(ctxInfo, gli); this->initStencilFormats(ctxInfo); /************************************************************************** * GrDrawTargetCaps fields **************************************************************************/ if (kGL_GrGLStandard == standard) { // we could also look for GL_ATI_separate_stencil extension or // GL_EXT_stencil_two_side but they use different function signatures // than GL2.0+ (and than each other). fTwoSidedStencilSupport = (ctxInfo.version() >= GR_GL_VER(2,0)); // supported on GL 1.4 and higher or by extension fStencilWrapOpsSupport = (ctxInfo.version() >= GR_GL_VER(1,4)) || ctxInfo.hasExtension("GL_EXT_stencil_wrap"); } else { // ES 2 has two sided stencil and stencil wrap fTwoSidedStencilSupport = true; fStencilWrapOpsSupport = true; } if (kGL_GrGLStandard == standard) { fMapBufferFlags = kCanMap_MapFlag; // we require VBO support and the desktop VBO // extension includes glMapBuffer. if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_ARB_map_buffer_range")) { fMapBufferFlags |= kSubset_MapFlag; fMapBufferType = kMapBufferRange_MapBufferType; } else { fMapBufferType = kMapBuffer_MapBufferType; } } else { // Unextended GLES2 doesn't have any buffer mapping. fMapBufferFlags = kNone_MapBufferType; if (ctxInfo.hasExtension("GL_CHROMIUM_map_sub")) { fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag; fMapBufferType = kChromium_MapBufferType; } else if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_EXT_map_buffer_range")) { fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag; fMapBufferType = kMapBufferRange_MapBufferType; } else if (ctxInfo.hasExtension("GL_OES_mapbuffer")) { fMapBufferFlags = kCanMap_MapFlag; fMapBufferType = kMapBuffer_MapBufferType; } } if (kGL_GrGLStandard == standard) { SkASSERT(ctxInfo.version() >= GR_GL_VER(2,0) || ctxInfo.hasExtension("GL_ARB_texture_non_power_of_two")); fNPOTTextureTileSupport = true; fMipMapSupport = true; } else { // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only // ES3 has no limitations. fNPOTTextureTileSupport = ctxInfo.version() >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_OES_texture_npot"); // ES2 supports MIP mapping for POT textures but our caps don't allow for limited MIP // support. The OES extension or ES 3.0 allow for MIPS on NPOT textures. So, apparently, // does the undocumented GL_IMG_texture_npot extension. This extension does not seem to // to alllow arbitrary wrap modes, however. fMipMapSupport = fNPOTTextureTileSupport || ctxInfo.hasExtension("GL_IMG_texture_npot"); } fHWAALineSupport = (kGL_GrGLStandard == standard); GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize); GR_GL_GetIntegerv(gli, GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize); // Our render targets are always created with textures as the color // attachment, hence this min: fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize); fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering") && ctxInfo.hasExtension("GL_EXT_direct_state_access"); fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker"); fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType; // Disable scratch texture reuse on Mali and Adreno devices fReuseScratchTextures = kARM_GrGLVendor != ctxInfo.vendor() && kQualcomm_GrGLVendor != ctxInfo.vendor(); // Enable supported shader-related caps if (kGL_GrGLStandard == standard) { fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_blend_func_extended"); fShaderDerivativeSupport = true; // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3,2) && ctxInfo.glslGeneration() >= k150_GrGLSLGeneration; } else { fShaderDerivativeSupport = ctxInfo.hasExtension("GL_OES_standard_derivatives"); } if (GrGLCaps::kES_IMG_MsToTexture_MSFBOType == fMSFBOType) { GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &fMaxSampleCount); } else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) { GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxSampleCount); } this->initConfigTexturableTable(ctxInfo, gli); this->initConfigRenderableTable(ctxInfo); return true; }
void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { this->reset(); if (!ctxInfo.isInitialized()) { return; } GrGLBinding binding = ctxInfo.binding(); GrGLVersion version = ctxInfo.version(); /************************************************************************** * Caps specific to GrGLCaps **************************************************************************/ if (kES2_GrGLBinding == binding) { GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &fMaxFragmentUniformVectors); } else { GrAssert(kDesktop_GrGLBinding == binding); GrGLint max; GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max); fMaxFragmentUniformVectors = max / 4; } GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes); if (kDesktop_GrGLBinding == binding) { fRGBA8RenderbufferSupport = true; } else { fRGBA8RenderbufferSupport = ctxInfo.hasExtension("GL_OES_rgb8_rgba8") || ctxInfo.hasExtension("GL_ARM_rgba8"); } if (kDesktop_GrGLBinding == binding) { fBGRAFormatSupport = version >= GR_GL_VER(1,2) || ctxInfo.hasExtension("GL_EXT_bgra"); } else { if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { fBGRAFormatSupport = true; } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { fBGRAFormatSupport = true; fBGRAIsInternalFormat = true; } GrAssert(fBGRAFormatSupport || kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig); } if (kDesktop_GrGLBinding == binding) { fTextureSwizzleSupport = version >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_texture_swizzle"); } else { fTextureSwizzleSupport = false; } if (kDesktop_GrGLBinding == binding) { fUnpackRowLengthSupport = true; fUnpackFlipYSupport = false; fPackRowLengthSupport = true; fPackFlipYSupport = false; } else { fUnpackRowLengthSupport =ctxInfo.hasExtension("GL_EXT_unpack_subimage"); fUnpackFlipYSupport = ctxInfo.hasExtension("GL_CHROMIUM_flipy"); // no extension for pack row length fPackRowLengthSupport = false; fPackFlipYSupport = ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order"); } fTextureUsageSupport = (kES2_GrGLBinding == binding) && ctxInfo.hasExtension("GL_ANGLE_texture_usage"); // Tex storage is in desktop 4.2 and can be an extension to desktop or ES. fTexStorageSupport = (kDesktop_GrGLBinding == binding && version >= GR_GL_VER(4,2)) || ctxInfo.hasExtension("GL_ARB_texture_storage") || ctxInfo.hasExtension("GL_EXT_texture_storage"); // ARB_texture_rg is part of OpenGL 3.0 if (kDesktop_GrGLBinding == binding) { fTextureRedSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_ARB_texture_rg"); } else { fTextureRedSupport = ctxInfo.hasExtension("GL_EXT_texture_rg"); } fImagingSupport = kDesktop_GrGLBinding == binding && ctxInfo.hasExtension("GL_ARB_imaging"); // ES 2 only guarantees RGBA/uchar + one other format/type combo for // ReadPixels. The other format has to checked at run-time since it // can change based on which render target is bound fTwoFormatLimit = kES2_GrGLBinding == binding; // Known issue on at least some Intel platforms: // http://code.google.com/p/skia/issues/detail?id=946 if (kIntel_GrGLVendor != ctxInfo.vendor()) { fFragCoordsConventionSupport = ctxInfo.glslGeneration() >= k150_GrGLSLGeneration || ctxInfo.hasExtension("GL_ARB_fragment_coord_conventions"); } // SGX and Mali GPUs that are based on a tiled-deferred architecture that have trouble with // frequently changing VBOs. We've measured a performance increase using non-VBO vertex // data for dynamic content on these GPUs. Perhaps we should read the renderer string and // limit this decision to specific GPU families rather than basing it on the vendor alone. if (!GR_GL_MUST_USE_VBO && (kARM_GrGLVendor == ctxInfo.vendor() || kImagination_GrGLVendor == ctxInfo.vendor())) { fUseNonVBOVertexAndIndexDynamicData = true; } if (kDesktop_GrGLBinding == binding && version >= GR_GL_VER(3, 2)) { GrGLint profileMask; GR_GL_GetIntegerv(gli, GR_GL_CONTEXT_PROFILE_MASK, &profileMask); fIsCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT); } fDiscardFBSupport = ctxInfo.hasExtension("GL_EXT_discard_framebuffer"); if (kDesktop_GrGLBinding == binding) { fVertexArrayObjectSupport = version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_ARB_vertex_array_object"); } else { fVertexArrayObjectSupport = ctxInfo.hasExtension("GL_OES_vertex_array_object"); } this->initFSAASupport(ctxInfo, gli); this->initStencilFormats(ctxInfo); /************************************************************************** * GrDrawTargetCaps fields **************************************************************************/ GrGLint maxTextureUnits; // check FS and fixed-function texture unit limits // we only use textures in the fragment stage currently. // checks are > to make sure we have a spare unit. GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); GrGLint numFormats; GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); SkAutoSTMalloc<10, GrGLint> formats(numFormats); GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < numFormats; ++i) { if (formats[i] == GR_GL_PALETTE8_RGBA8) { f8BitPaletteSupport = true; break; } } if (kDesktop_GrGLBinding == binding) { // we could also look for GL_ATI_separate_stencil extension or // GL_EXT_stencil_two_side but they use different function signatures // than GL2.0+ (and than each other). fTwoSidedStencilSupport = (ctxInfo.version() >= GR_GL_VER(2,0)); // supported on GL 1.4 and higher or by extension fStencilWrapOpsSupport = (ctxInfo.version() >= GR_GL_VER(1,4)) || ctxInfo.hasExtension("GL_EXT_stencil_wrap"); } else { // ES 2 has two sided stencil and stencil wrap fTwoSidedStencilSupport = true; fStencilWrapOpsSupport = true; } if (kDesktop_GrGLBinding == binding) { fBufferLockSupport = true; // we require VBO support and the desktop VBO extension includes // glMapBuffer. } else { fBufferLockSupport = ctxInfo.hasExtension("GL_OES_mapbuffer"); } if (kDesktop_GrGLBinding == binding) { if (ctxInfo.version() >= GR_GL_VER(2,0) || ctxInfo.hasExtension("GL_ARB_texture_non_power_of_two")) { fNPOTTextureTileSupport = true; } else { fNPOTTextureTileSupport = false; } } else { // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only fNPOTTextureTileSupport = ctxInfo.hasExtension("GL_OES_texture_npot"); } fHWAALineSupport = (kDesktop_GrGLBinding == binding); GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize); GR_GL_GetIntegerv(gli, GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize); // Our render targets are always created with textures as the color // attachment, hence this min: fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize); fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING && ctxInfo.hasExtension("GL_NV_path_rendering"); // Enable supported shader-related caps if (kDesktop_GrGLBinding == binding) { fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_blend_func_extended"); fShaderDerivativeSupport = true; // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3,2) && ctxInfo.glslGeneration() >= k150_GrGLSLGeneration; } else { fShaderDerivativeSupport = ctxInfo.hasExtension("GL_OES_standard_derivatives"); } if (GrGLCaps::kImaginationES_MSFBOType == fMSFBOType) { GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &fMaxSampleCount); } else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) { GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxSampleCount); } }
void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { GrGLStandard standard = ctxInfo.standard(); GrGLVersion version = ctxInfo.version(); // Base texture support fConfigTextureSupport[kAlpha_8_GrPixelConfig] = true; fConfigTextureSupport[kRGB_565_GrPixelConfig] = true; fConfigTextureSupport[kRGBA_4444_GrPixelConfig] = true; fConfigTextureSupport[kRGBA_8888_GrPixelConfig] = true; // Check for 8-bit palette.. GrGLint numFormats; GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); if (numFormats) { SkAutoSTMalloc<10, GrGLint> formats(numFormats); GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < numFormats; ++i) { if (GR_GL_PALETTE8_RGBA8 == formats[i]) { fConfigTextureSupport[kIndex_8_GrPixelConfig] = true; break; } } } // Check for BGRA if (kGL_GrGLStandard == standard) { fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = version >= GR_GL_VER(1,2) || ctxInfo.hasExtension("GL_EXT_bgra"); } else { if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; fBGRAIsInternalFormat = true; } SkASSERT(fConfigTextureSupport[kBGRA_8888_GrPixelConfig] || kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig); } // Compressed texture support // glCompressedTexImage2D is available on all OpenGL ES devices... // however, it is only available on standard OpenGL after version 1.3 bool hasCompressTex2D = (kGL_GrGLStandard != standard || version >= GR_GL_VER(1, 3)); // Check for ETC1 bool hasETC1 = false; // First check version for support if (kGL_GrGLStandard == standard) { hasETC1 = hasCompressTex2D && (version >= GR_GL_VER(4, 3) || ctxInfo.hasExtension("GL_ARB_ES3_compatibility")); } else { hasETC1 = hasCompressTex2D && (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_OES_compressed_ETC1_RGB8_texture") || // ETC2 is a superset of ETC1, so we can just check for that, too. (ctxInfo.hasExtension("GL_OES_compressed_ETC2_RGB8_texture") && ctxInfo.hasExtension("GL_OES_compressed_ETC2_RGBA8_texture"))); } fConfigTextureSupport[kETC1_GrPixelConfig] = hasETC1; // Check for LATC under its various forms LATCAlias alias = kLATC_LATCAlias; bool hasLATC = hasCompressTex2D && (ctxInfo.hasExtension("GL_EXT_texture_compression_latc") || ctxInfo.hasExtension("GL_NV_texture_compression_latc")); // Check for RGTC if (!hasLATC) { // If we're using OpenGL 3.0 or later, then we have RGTC, an identical compression format. if (kGL_GrGLStandard == standard) { hasLATC = version >= GR_GL_VER(3, 0); } if (!hasLATC) { hasLATC = ctxInfo.hasExtension("GL_EXT_texture_compression_rgtc") || ctxInfo.hasExtension("GL_ARB_texture_compression_rgtc"); } if (hasLATC) { alias = kRGTC_LATCAlias; } } // Check for 3DC if (!hasLATC) { hasLATC = ctxInfo.hasExtension("GL_AMD_compressed_3DC_texture"); if (hasLATC) { alias = k3DC_LATCAlias; } } fConfigTextureSupport[kLATC_GrPixelConfig] = hasLATC; fLATCAlias = alias; }
void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { GrGLStandard standard = ctxInfo.standard(); GrGLVersion version = ctxInfo.version(); // Base texture support fConfigTextureSupport[kAlpha_8_GrPixelConfig] = true; fConfigTextureSupport[kRGB_565_GrPixelConfig] = true; fConfigTextureSupport[kRGBA_4444_GrPixelConfig] = true; fConfigTextureSupport[kRGBA_8888_GrPixelConfig] = true; // Check for 8-bit palette.. GrGLint numFormats; GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); if (numFormats) { SkAutoSTMalloc<10, GrGLint> formats(numFormats); GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < numFormats; ++i) { if (GR_GL_PALETTE8_RGBA8 == formats[i]) { fConfigTextureSupport[kIndex_8_GrPixelConfig] = true; break; } } } // Check for BGRA if (kGL_GrGLStandard == standard) { fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = version >= GR_GL_VER(1,2) || ctxInfo.hasExtension("GL_EXT_bgra"); } else { if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true; fBGRAIsInternalFormat = true; } SkASSERT(fConfigTextureSupport[kBGRA_8888_GrPixelConfig] || kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig); } // Check for sRGBA if (kGL_GrGLStandard == standard) { fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_texture_sRGB")); } else { fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_sRGB")); } // Compressed texture support // glCompressedTexImage2D is available on all OpenGL ES devices... // however, it is only available on standard OpenGL after version 1.3 bool hasCompressTex2D = (kGL_GrGLStandard != standard || version >= GR_GL_VER(1, 3)); fCompressedTexSubImageSupport = hasCompressTex2D && (gli->fFunctions.fCompressedTexSubImage2D); // Check for ETC1 bool hasETC1 = false; // First check version for support if (kGL_GrGLStandard == standard) { hasETC1 = hasCompressTex2D && (version >= GR_GL_VER(4, 3) || ctxInfo.hasExtension("GL_ARB_ES3_compatibility")); } else { hasETC1 = hasCompressTex2D && (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_OES_compressed_ETC1_RGB8_texture") || // ETC2 is a superset of ETC1, so we can just check for that, too. (ctxInfo.hasExtension("GL_OES_compressed_ETC2_RGB8_texture") && ctxInfo.hasExtension("GL_OES_compressed_ETC2_RGBA8_texture"))); } fConfigTextureSupport[kETC1_GrPixelConfig] = hasETC1; // Check for LATC under its various forms LATCAlias alias = kLATC_LATCAlias; bool hasLATC = hasCompressTex2D && (ctxInfo.hasExtension("GL_EXT_texture_compression_latc") || ctxInfo.hasExtension("GL_NV_texture_compression_latc")); // Check for RGTC if (!hasLATC) { // If we're using OpenGL 3.0 or later, then we have RGTC, an identical compression format. if (kGL_GrGLStandard == standard) { hasLATC = version >= GR_GL_VER(3, 0); } if (!hasLATC) { hasLATC = ctxInfo.hasExtension("GL_EXT_texture_compression_rgtc") || ctxInfo.hasExtension("GL_ARB_texture_compression_rgtc"); } if (hasLATC) { alias = kRGTC_LATCAlias; } } // Check for 3DC if (!hasLATC) { hasLATC = ctxInfo.hasExtension("GL_AMD_compressed_3DC_texture"); if (hasLATC) { alias = k3DC_LATCAlias; } } fConfigTextureSupport[kLATC_GrPixelConfig] = hasLATC; fLATCAlias = alias; // Check for R11_EAC ... We don't support R11_EAC on desktop, as most // cards default to decompressing the textures in the driver, and is // generally slower. if (kGL_GrGLStandard != standard) { fConfigTextureSupport[kR11_EAC_GrPixelConfig] = version >= GR_GL_VER(3, 0); } // Check for ASTC fConfigTextureSupport[kASTC_12x12_GrPixelConfig] = ctxInfo.hasExtension("GL_KHR_texture_compression_astc_hdr") || ctxInfo.hasExtension("GL_KHR_texture_compression_astc_ldr") || ctxInfo.hasExtension("GL_OES_texture_compression_astc"); // Check for floating point texture support // NOTE: We disallow floating point textures on ES devices if linear // filtering modes are not supported. This is for simplicity, but a more // granular approach is possible. Coincidentally, floating point textures became part of // the standard in ES3.1 / OGL 3.1, hence the shorthand bool hasFPTextures = version >= GR_GL_VER(3, 1); if (!hasFPTextures) { hasFPTextures = ctxInfo.hasExtension("GL_ARB_texture_float") || (ctxInfo.hasExtension("GL_OES_texture_float_linear") && ctxInfo.hasExtension("GL_OES_texture_float")); } fConfigTextureSupport[kRGBA_float_GrPixelConfig] = hasFPTextures; // Check for fp16 texture support // NOTE: We disallow floating point textures on ES devices if linear // filtering modes are not supported. This is for simplicity, but a more // granular approach is possible. Coincidentally, 16-bit floating point textures became part of // the standard in ES3.1 / OGL 3.1, hence the shorthand bool hasHalfFPTextures = version >= GR_GL_VER(3, 1); if (!hasHalfFPTextures) { hasHalfFPTextures = ctxInfo.hasExtension("GL_ARB_texture_float") || (ctxInfo.hasExtension("GL_OES_texture_half_float_linear") && ctxInfo.hasExtension("GL_OES_texture_half_float")); } fConfigTextureSupport[kAlpha_half_GrPixelConfig] = hasHalfFPTextures; }
int SDL_main(int argc, char** argv) { #else int main(int argc, char** argv) { #endif uint32_t windowFlags = 0; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GLContext glContext = nullptr; #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS) // For Android/iOS we need to set up for OpenGL ES and we make the window hi res & full screen SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_ALLOW_HIGHDPI; #else // For all other clients we use the core profile and operate in a window SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; #endif static const int kStencilBits = 8; // Skia needs 8 stencil bits SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, kStencilBits); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); // If you want multisampling, uncomment the below lines and set a sample count static const int kMsaaSampleCount = 0; //4; // SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); // SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, kMsaaSampleCount); /* * In a real application you might want to initialize more subsystems */ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { handle_error(); return 1; } // Setup window // This code will create a window with the same resolution as the user's desktop. SDL_DisplayMode dm; if (SDL_GetDesktopDisplayMode(0, &dm) != 0) { handle_error(); return 1; } SDL_Window* window = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, dm.w, dm.h, windowFlags); if (!window) { handle_error(); return 1; } // To go fullscreen // SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); // try and setup a GL context glContext = SDL_GL_CreateContext(window); if (!glContext) { handle_error(); return 1; } int success = SDL_GL_MakeCurrent(window, glContext); if (success != 0) { handle_error(); return success; } uint32_t windowFormat = SDL_GetWindowPixelFormat(window); int contextType; SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &contextType); int dw, dh; SDL_GL_GetDrawableSize(window, &dw, &dh); glViewport(0, 0, dw, dh); glClearColor(1, 1, 1, 1); glClearStencil(0); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // setup GrContext auto interface = GrGLMakeNativeInterface(); // setup contexts sk_sp<GrContext> grContext(GrContext::MakeGL(interface)); SkASSERT(grContext); // Wrap the frame buffer object attached to the screen in a Skia render target so Skia can // render to it GrGLint buffer; GR_GL_GetIntegerv(interface.get(), GR_GL_FRAMEBUFFER_BINDING, &buffer); GrGLFramebufferInfo info; info.fFBOID = (GrGLuint) buffer; SkColorType colorType; //SkDebugf("%s", SDL_GetPixelFormatName(windowFormat)); // TODO: the windowFormat is never any of these? if (SDL_PIXELFORMAT_RGBA8888 == windowFormat) { info.fFormat = GR_GL_RGBA8; colorType = kRGBA_8888_SkColorType; } else { colorType = kBGRA_8888_SkColorType; if (SDL_GL_CONTEXT_PROFILE_ES == contextType) { info.fFormat = GR_GL_BGRA8; } else { // We assume the internal format is RGBA8 on desktop GL info.fFormat = GR_GL_RGBA8; } } GrBackendRenderTarget target(dw, dh, kMsaaSampleCount, kStencilBits, info); // setup SkSurface // To use distance field text, use commented out SkSurfaceProps instead // SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, // SkSurfaceProps::kLegacyFontHost_InitType); SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target, kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props)); SkCanvas* canvas = surface->getCanvas(); canvas->scale((float)dw/dm.w, (float)dh/dm.h); ApplicationState state; const char* helpMessage = "Click and drag to create rects. Press esc to quit."; SkPaint paint; // create a surface for CPU rasterization sk_sp<SkSurface> cpuSurface(SkSurface::MakeRaster(canvas->imageInfo())); SkCanvas* offscreen = cpuSurface->getCanvas(); offscreen->save(); offscreen->translate(50.0f, 50.0f); offscreen->drawPath(create_star(), paint); offscreen->restore(); sk_sp<SkImage> image = cpuSurface->makeImageSnapshot(); int rotation = 0; SkFont font; while (!state.fQuit) { // Our application loop SkRandom rand; canvas->clear(SK_ColorWHITE); handle_events(&state, canvas); paint.setColor(SK_ColorBLACK); canvas->drawString(helpMessage, 100.0f, 100.0f, font, paint); for (int i = 0; i < state.fRects.count(); i++) { paint.setColor(rand.nextU() | 0x44808080); canvas->drawRect(state.fRects[i], paint); } // draw offscreen canvas canvas->save(); canvas->translate(dm.w / 2.0, dm.h / 2.0); canvas->rotate(rotation++); canvas->drawImage(image, -50.0f, -50.0f); canvas->restore(); canvas->flush(); SDL_GL_SwapWindow(window); } if (glContext) { SDL_GL_DeleteContext(glContext); } //Destroy window SDL_DestroyWindow(window); //Quit SDL subsystems SDL_Quit(); return 0; }
void GrGLCaps::init(const GrGLContextInfo& ctxInfo) { this->reset(); if (!ctxInfo.isInitialized()) { return; } const GrGLInterface* gli = ctxInfo.interface(); GrGLBinding binding = ctxInfo.binding(); GrGLVersion version = ctxInfo.version(); if (kES2_GrGLBinding == binding) { GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &fMaxFragmentUniformVectors); } else { GrAssert(kDesktop_GrGLBinding == binding); GrGLint max; GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max); fMaxFragmentUniformVectors = max / 4; } GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes); if (kDesktop_GrGLBinding == binding) { fRGBA8RenderbufferSupport = true; } else { fRGBA8RenderbufferSupport = ctxInfo.hasExtension("GL_OES_rgb8_rgba8") || ctxInfo.hasExtension("GL_ARM_rgba8"); } if (kDesktop_GrGLBinding == binding) { fBGRAFormatSupport = version >= GR_GL_VER(1,2) || ctxInfo.hasExtension("GL_EXT_bgra"); } else { if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { fBGRAFormatSupport = true; } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { fBGRAFormatSupport = true; fBGRAIsInternalFormat = true; } GrAssert(fBGRAFormatSupport || kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig); } if (kDesktop_GrGLBinding == binding) { fTextureSwizzleSupport = version >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_texture_swizzle"); } else { fTextureSwizzleSupport = false; } if (kDesktop_GrGLBinding == binding) { fUnpackRowLengthSupport = true; fUnpackFlipYSupport = false; fPackRowLengthSupport = true; fPackFlipYSupport = false; } else { fUnpackRowLengthSupport =ctxInfo.hasExtension("GL_EXT_unpack_subimage"); fUnpackFlipYSupport = ctxInfo.hasExtension("GL_CHROMIUM_flipy"); // no extension for pack row length fPackRowLengthSupport = false; fPackFlipYSupport = ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order"); } fTextureUsageSupport = (kES2_GrGLBinding == binding) && ctxInfo.hasExtension("GL_ANGLE_texture_usage"); // Tex storage is in desktop 4.2 and can be an extension to desktop or ES. fTexStorageSupport = (kDesktop_GrGLBinding == binding && version >= GR_GL_VER(4,2)) || ctxInfo.hasExtension("GL_ARB_texture_storage") || ctxInfo.hasExtension("GL_EXT_texture_storage"); // ARB_texture_rg is part of OpenGL 3.0 if (kDesktop_GrGLBinding == binding) { fTextureRedSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_ARB_texture_rg"); } else { fTextureRedSupport = ctxInfo.hasExtension("GL_EXT_texture_rg"); } fImagingSupport = kDesktop_GrGLBinding == binding && ctxInfo.hasExtension("GL_ARB_imaging"); // ES 2 only guarantees RGBA/uchar + one other format/type combo for // ReadPixels. The other format has to checked at run-time since it // can change based on which render target is bound fTwoFormatLimit = kES2_GrGLBinding == binding; // Known issue on at least some Intel platforms: // http://code.google.com/p/skia/issues/detail?id=946 if (kIntel_GrGLVendor != ctxInfo.vendor()) { fFragCoordsConventionSupport = ctxInfo.glslGeneration() >= k150_GrGLSLGeneration || ctxInfo.hasExtension("GL_ARB_fragment_coord_conventions"); } this->initFSAASupport(ctxInfo); this->initStencilFormats(ctxInfo); }