1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GLBench.h" 9 10#if SK_SUPPORT_GPU 11#include "GrTest.h" 12#include <stdio.h> 13 14const GrGLContext* GLBench::getGLContext(SkCanvas* canvas) { 15 // This bench exclusively tests GL calls directly 16 if (nullptr == canvas->getGrContext()) { 17 return nullptr; 18 } 19 GrContext* context = canvas->getGrContext(); 20 GrGpu* gpu = context->getGpu(); 21 if (!gpu) { 22 SkDebugf("Couldn't get Gr gpu."); 23 return nullptr; 24 } 25 26 const GrGLContext* ctx = gpu->glContextForTesting(); 27 if (!ctx) { 28 SkDebugf("Couldn't get an interface\n"); 29 return nullptr; 30 } 31 32 return this->onGetGLContext(ctx); 33} 34 35void GLBench::onPreDraw(SkCanvas* canvas) { 36 // This bench exclusively tests GL calls directly 37 const GrGLContext* ctx = this->getGLContext(canvas); 38 if (!ctx) { 39 return; 40 } 41 this->setup(ctx); 42} 43 44void GLBench::onPostDraw(SkCanvas* canvas) { 45 // This bench exclusively tests GL calls directly 46 const GrGLContext* ctx = this->getGLContext(canvas); 47 if (!ctx) { 48 return; 49 } 50 this->teardown(ctx->interface()); 51} 52 53void GLBench::onDraw(int loops, SkCanvas* canvas) { 54 const GrGLContext* ctx = this->getGLContext(canvas); 55 if (!ctx) { 56 return; 57 } 58 this->glDraw(loops, ctx); 59} 60 61GrGLuint GLBench::CompileShader(const GrGLInterface* gl, const char* shaderSrc, GrGLenum type) { 62 GrGLuint shader; 63 // Create the shader object 64 GR_GL_CALL_RET(gl, shader, CreateShader(type)); 65 66 // Load the shader source 67 GR_GL_CALL(gl, ShaderSource(shader, 1, &shaderSrc, nullptr)); 68 69 // Compile the shader 70 GR_GL_CALL(gl, CompileShader(shader)); 71 72 // Check for compile time errors 73 GrGLint success = GR_GL_INIT_ZERO; 74 GrGLchar infoLog[512]; 75 GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success)); 76 if (!success) { 77 GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, nullptr, infoLog)); 78 SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog); 79 } 80 81 return shader; 82} 83 84GrGLuint GLBench::CreateProgram(const GrGLInterface* gl, const char* vshader, const char* fshader) { 85 86 GrGLuint vertexShader = CompileShader(gl, vshader, GR_GL_VERTEX_SHADER); 87 GrGLuint fragmentShader = CompileShader(gl, fshader, GR_GL_FRAGMENT_SHADER); 88 89 GrGLuint shaderProgram; 90 GR_GL_CALL_RET(gl, shaderProgram, CreateProgram()); 91 GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader)); 92 GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader)); 93 GR_GL_CALL(gl, LinkProgram(shaderProgram)); 94 95 // Check for linking errors 96 GrGLint success = GR_GL_INIT_ZERO; 97 GrGLchar infoLog[512]; 98 GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success)); 99 if (!success) { 100 GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, nullptr, infoLog)); 101 SkDebugf("Linker Error: %s\n", infoLog); 102 } 103 GR_GL_CALL(gl, DeleteShader(vertexShader)); 104 GR_GL_CALL(gl, DeleteShader(fragmentShader)); 105 106 return shaderProgram; 107} 108 109GrGLuint GLBench::SetupFramebuffer(const GrGLInterface* gl, int screenWidth, int screenHeight) { 110 //Setup framebuffer 111 GrGLuint texture; 112 GR_GL_CALL(gl, GenTextures(1, &texture)); 113 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE7)); 114 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texture)); 115 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST)); 116 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST)); 117 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE)); 118 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE)); 119 GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 120 0, //level 121 GR_GL_RGBA, //internal format 122 screenWidth, // width 123 screenHeight, // height 124 0, //border 125 GR_GL_RGBA, //format 126 GR_GL_UNSIGNED_BYTE, // type 127 nullptr)); 128 129 // bind framebuffer 130 GrGLuint framebuffer; 131 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); 132 GR_GL_CALL(gl, GenFramebuffers(1, &framebuffer)); 133 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, framebuffer)); 134 GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER, 135 GR_GL_COLOR_ATTACHMENT0, 136 GR_GL_TEXTURE_2D, 137 texture, 0)); 138 GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 139 GR_GL_CALL(gl, Viewport(0, 0, screenWidth, screenHeight)); 140 return texture; 141} 142 143 144void GLBench::DumpImage(const GrGLInterface* gl, uint32_t screenWidth, uint32_t screenHeight, 145 const char* filename) { 146 // read back pixels 147 SkAutoTArray<uint32_t> readback(screenWidth * screenHeight); 148 GR_GL_CALL(gl, ReadPixels(0, // x 149 0, // y 150 screenWidth, // width 151 screenHeight, // height 152 GR_GL_RGBA, //format 153 GR_GL_UNSIGNED_BYTE, //type 154 readback.get())); 155 156 // dump png 157 SkBitmap bm; 158 if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(screenWidth, screenHeight))) { 159 SkDebugf("couldn't allocate bitmap\n"); 160 return; 161 } 162 163 bm.setPixels(readback.get()); 164 165 if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100)) { 166 SkDebugf("------ failed to encode %s\n", filename); 167 remove(filename); // remove any partial file 168 return; 169 } 170} 171 172#endif 173