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 "GrGpu.h"
12 #include "GrTest.h"
13 #include "gl/GrGLContext.h"
14 #include "gl/builders/GrGLShaderStringBuilder.h"
15 #include "SkSLCompiler.h"
16 #include <stdio.h>
17
18 #include "sk_tool_utils.h"
19
getGLContext(SkCanvas * canvas)20 const GrGLContext* GLBench::getGLContext(SkCanvas* canvas) {
21 // This bench exclusively tests GL calls directly
22 if (nullptr == canvas->getGrContext()) {
23 return nullptr;
24 }
25 GrContext* context = canvas->getGrContext();
26 GrGpu* gpu = context->getGpu();
27 if (!gpu) {
28 SkDebugf("Couldn't get Gr gpu.");
29 return nullptr;
30 }
31
32 const GrGLContext* ctx = gpu->glContextForTesting();
33 if (!ctx) {
34 SkDebugf("Couldn't get an interface\n");
35 return nullptr;
36 }
37
38 return this->onGetGLContext(ctx);
39 }
40
onPreDraw(SkCanvas * canvas)41 void GLBench::onPreDraw(SkCanvas* canvas) {
42 // This bench exclusively tests GL calls directly
43 const GrGLContext* ctx = this->getGLContext(canvas);
44 if (!ctx) {
45 return;
46 }
47 this->setup(ctx);
48 }
49
onPostDraw(SkCanvas * canvas)50 void GLBench::onPostDraw(SkCanvas* canvas) {
51 // This bench exclusively tests GL calls directly
52 const GrGLContext* ctx = this->getGLContext(canvas);
53 if (!ctx) {
54 return;
55 }
56 this->teardown(ctx->interface());
57 }
58
onDraw(int loops,SkCanvas * canvas)59 void GLBench::onDraw(int loops, SkCanvas* canvas) {
60 const GrGLContext* ctx = this->getGLContext(canvas);
61 if (!ctx) {
62 return;
63 }
64 this->glDraw(loops, ctx);
65 canvas->getGrContext()->resetContext();
66 }
67
CompileShader(const GrGLContext * context,const char * sksl,GrGLenum type)68 GrGLuint GLBench::CompileShader(const GrGLContext* context, const char* sksl, GrGLenum type) {
69 const GrGLInterface* gl = context->interface();
70 SkSL::String glsl;
71 SkSL::Program::Settings settings;
72 settings.fCaps = context->caps()->shaderCaps();
73 std::unique_ptr<SkSL::Program> program = context->compiler()->convertProgram(
74 type == GR_GL_VERTEX_SHADER ? SkSL::Program::kVertex_Kind
75 : SkSL::Program::kFragment_Kind,
76 SkString(sksl),
77 settings);
78 if (!program || !context->compiler()->toGLSL(*program, &glsl)) {
79 SkDebugf("SkSL compilation failed:\n%s\n%s\n", sksl,
80 context->compiler()->errorText().c_str());
81 }
82 GrGLuint shader;
83 // Create the shader object
84 GR_GL_CALL_RET(gl, shader, CreateShader(type));
85
86 // Load the shader source
87 const char* glslPtr = glsl.c_str();
88 GR_GL_CALL(gl, ShaderSource(shader, 1, (const char**) &glslPtr, nullptr));
89
90 // Compile the shader
91 GR_GL_CALL(gl, CompileShader(shader));
92
93 // Check for compile time errors
94 GrGLint success = GR_GL_INIT_ZERO;
95 GrGLchar infoLog[512];
96 GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success));
97 if (!success) {
98 GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, nullptr, infoLog));
99 SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog);
100 }
101
102 return shader;
103 }
104
CreateProgram(const GrGLContext * context,const char * vshader,const char * fshader)105 GrGLuint GLBench::CreateProgram(const GrGLContext* context, const char* vshader,
106 const char* fshader) {
107 const GrGLInterface* gl = context->interface();
108 GrGLuint vertexShader = CompileShader(context, vshader, GR_GL_VERTEX_SHADER);
109 GrGLuint fragmentShader = CompileShader(context, fshader, GR_GL_FRAGMENT_SHADER);
110
111 GrGLuint shaderProgram;
112 GR_GL_CALL_RET(gl, shaderProgram, CreateProgram());
113 GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader));
114 GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader));
115 GR_GL_CALL(gl, LinkProgram(shaderProgram));
116
117 // Check for linking errors
118 GrGLint success = GR_GL_INIT_ZERO;
119 GrGLchar infoLog[512];
120 GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success));
121 if (!success) {
122 GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, nullptr, infoLog));
123 SkDebugf("Linker Error: %s\n", infoLog);
124 }
125 GR_GL_CALL(gl, DeleteShader(vertexShader));
126 GR_GL_CALL(gl, DeleteShader(fragmentShader));
127
128 return shaderProgram;
129 }
130
SetupFramebuffer(const GrGLInterface * gl,int screenWidth,int screenHeight)131 GrGLuint GLBench::SetupFramebuffer(const GrGLInterface* gl, int screenWidth, int screenHeight) {
132 //Setup framebuffer
133 GrGLuint texture;
134 GR_GL_CALL(gl, GenTextures(1, &texture));
135 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE7));
136 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texture));
137 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
138 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
139 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
140 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
141 GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D,
142 0, //level
143 GR_GL_RGBA, //internal format
144 screenWidth, // width
145 screenHeight, // height
146 0, //border
147 GR_GL_RGBA, //format
148 GR_GL_UNSIGNED_BYTE, // type
149 nullptr));
150
151 // bind framebuffer
152 GrGLuint framebuffer;
153 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
154 GR_GL_CALL(gl, GenFramebuffers(1, &framebuffer));
155 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, framebuffer));
156 GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
157 GR_GL_COLOR_ATTACHMENT0,
158 GR_GL_TEXTURE_2D,
159 texture, 0));
160 GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
161 GR_GL_CALL(gl, Viewport(0, 0, screenWidth, screenHeight));
162 return texture;
163 }
164
165
DumpImage(const GrGLInterface * gl,uint32_t screenWidth,uint32_t screenHeight,const char * filename)166 void GLBench::DumpImage(const GrGLInterface* gl, uint32_t screenWidth, uint32_t screenHeight,
167 const char* filename) {
168 // read back pixels
169 SkAutoTArray<uint32_t> readback(screenWidth * screenHeight);
170 GR_GL_CALL(gl, ReadPixels(0, // x
171 0, // y
172 screenWidth, // width
173 screenHeight, // height
174 GR_GL_RGBA, //format
175 GR_GL_UNSIGNED_BYTE, //type
176 readback.get()));
177
178 // dump png
179 SkBitmap bm;
180 if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(screenWidth, screenHeight))) {
181 SkDebugf("couldn't allocate bitmap\n");
182 return;
183 }
184
185 bm.setPixels(readback.get());
186
187 if (!sk_tool_utils::EncodeImageToFile(filename, bm, SkEncodedImageFormat::kPNG, 100)) {
188 SkDebugf("------ failed to encode %s\n", filename);
189 remove(filename); // remove any partial file
190 return;
191 }
192 }
193
194 #endif
195