blob: b6975508cfe7335b4bc4e5743348b181d80aaf50 [file] [log] [blame]
joshualitt74a07db2015-07-01 12:39:07 -07001/*
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
robertphillips87f15c82016-05-20 11:14:33 -070011#include "GrGpu.h"
joshualitt74a07db2015-07-01 12:39:07 -070012#include "GrTest.h"
robertphillips87f15c82016-05-20 11:14:33 -070013#include "gl/GrGLContext.h"
ethannicholas5961bc92016-10-12 06:39:56 -070014#include "gl/builders/GrGLShaderStringBuilder.h"
15#include "SkSLCompiler.h"
joshualitt74a07db2015-07-01 12:39:07 -070016#include <stdio.h>
ethannicholas5961bc92016-10-12 06:39:56 -070017#include <string>
joshualitt74a07db2015-07-01 12:39:07 -070018
19const GrGLContext* GLBench::getGLContext(SkCanvas* canvas) {
20 // This bench exclusively tests GL calls directly
halcanary96fcdcc2015-08-27 07:41:13 -070021 if (nullptr == canvas->getGrContext()) {
22 return nullptr;
joshualitt74a07db2015-07-01 12:39:07 -070023 }
24 GrContext* context = canvas->getGrContext();
jvanverth672bb7f2015-07-13 07:19:57 -070025 GrGpu* gpu = context->getGpu();
26 if (!gpu) {
27 SkDebugf("Couldn't get Gr gpu.");
halcanary96fcdcc2015-08-27 07:41:13 -070028 return nullptr;
joshualitt74a07db2015-07-01 12:39:07 -070029 }
30
jvanverth672bb7f2015-07-13 07:19:57 -070031 const GrGLContext* ctx = gpu->glContextForTesting();
joshualitt74a07db2015-07-01 12:39:07 -070032 if (!ctx) {
33 SkDebugf("Couldn't get an interface\n");
halcanary96fcdcc2015-08-27 07:41:13 -070034 return nullptr;
joshualitt74a07db2015-07-01 12:39:07 -070035 }
36
37 return this->onGetGLContext(ctx);
38}
39
joshualitt8a6697a2015-09-30 12:11:07 -070040void GLBench::onPreDraw(SkCanvas* canvas) {
joshualitt74a07db2015-07-01 12:39:07 -070041 // This bench exclusively tests GL calls directly
42 const GrGLContext* ctx = this->getGLContext(canvas);
43 if (!ctx) {
44 return;
45 }
46 this->setup(ctx);
47}
48
joshualitt8a6697a2015-09-30 12:11:07 -070049void GLBench::onPostDraw(SkCanvas* canvas) {
joshualitt74a07db2015-07-01 12:39:07 -070050 // This bench exclusively tests GL calls directly
51 const GrGLContext* ctx = this->getGLContext(canvas);
52 if (!ctx) {
53 return;
54 }
55 this->teardown(ctx->interface());
56}
57
mtkleina1ebeb22015-10-01 09:43:39 -070058void GLBench::onDraw(int loops, SkCanvas* canvas) {
joshualitt74a07db2015-07-01 12:39:07 -070059 const GrGLContext* ctx = this->getGLContext(canvas);
60 if (!ctx) {
61 return;
62 }
63 this->glDraw(loops, ctx);
brianosman393c2ff2016-05-11 08:49:59 -070064 canvas->getGrContext()->resetContext();
joshualitt74a07db2015-07-01 12:39:07 -070065}
66
ethannicholas5961bc92016-10-12 06:39:56 -070067GrGLuint GLBench::CompileShader(const GrGLContext* context, const char* sksl, GrGLenum type) {
68 const GrGLInterface* gl = context->interface();
69 std::string glsl;
70 bool result = context->compiler()->toGLSL(type == GR_GL_VERTEX_SHADER
71 ? SkSL::Program::kVertex_Kind
72 : SkSL::Program::kFragment_Kind,
73 std::string(sksl),
74 GrGLSkSLCapsForContext(*context),
75 &glsl);
76 if (!result) {
77 SkDebugf("SkSL compilation failed:\n%s\n%s\n", sksl,
78 context->compiler()->errorText().c_str());
79 }
joshualitt74a07db2015-07-01 12:39:07 -070080 GrGLuint shader;
81 // Create the shader object
82 GR_GL_CALL_RET(gl, shader, CreateShader(type));
83
84 // Load the shader source
ethannicholas5961bc92016-10-12 06:39:56 -070085 const char* glslPtr = glsl.c_str();
86 GR_GL_CALL(gl, ShaderSource(shader, 1, (const char**) &glslPtr, nullptr));
joshualitt74a07db2015-07-01 12:39:07 -070087
88 // Compile the shader
89 GR_GL_CALL(gl, CompileShader(shader));
90
91 // Check for compile time errors
hendrikw894a2e42015-09-08 15:18:56 -070092 GrGLint success = GR_GL_INIT_ZERO;
joshualitt74a07db2015-07-01 12:39:07 -070093 GrGLchar infoLog[512];
94 GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success));
95 if (!success) {
halcanary96fcdcc2015-08-27 07:41:13 -070096 GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, nullptr, infoLog));
joshualitt74a07db2015-07-01 12:39:07 -070097 SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog);
98 }
99
100 return shader;
101}
102
ethannicholas5961bc92016-10-12 06:39:56 -0700103GrGLuint GLBench::CreateProgram(const GrGLContext* context, const char* vshader,
104 const char* fshader) {
105 const GrGLInterface* gl = context->interface();
106 GrGLuint vertexShader = CompileShader(context, vshader, GR_GL_VERTEX_SHADER);
107 GrGLuint fragmentShader = CompileShader(context, fshader, GR_GL_FRAGMENT_SHADER);
joshualitt74a07db2015-07-01 12:39:07 -0700108
109 GrGLuint shaderProgram;
110 GR_GL_CALL_RET(gl, shaderProgram, CreateProgram());
111 GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader));
112 GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader));
113 GR_GL_CALL(gl, LinkProgram(shaderProgram));
114
115 // Check for linking errors
hendrikw894a2e42015-09-08 15:18:56 -0700116 GrGLint success = GR_GL_INIT_ZERO;
joshualitt74a07db2015-07-01 12:39:07 -0700117 GrGLchar infoLog[512];
118 GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success));
119 if (!success) {
halcanary96fcdcc2015-08-27 07:41:13 -0700120 GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, nullptr, infoLog));
joshualitt74a07db2015-07-01 12:39:07 -0700121 SkDebugf("Linker Error: %s\n", infoLog);
122 }
123 GR_GL_CALL(gl, DeleteShader(vertexShader));
124 GR_GL_CALL(gl, DeleteShader(fragmentShader));
125
126 return shaderProgram;
127}
128
129GrGLuint GLBench::SetupFramebuffer(const GrGLInterface* gl, int screenWidth, int screenHeight) {
130 //Setup framebuffer
131 GrGLuint texture;
132 GR_GL_CALL(gl, GenTextures(1, &texture));
joshualittb2351682015-10-02 06:49:23 -0700133 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE7));
joshualitt74a07db2015-07-01 12:39:07 -0700134 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texture));
135 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
136 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
137 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
138 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
139 GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D,
140 0, //level
141 GR_GL_RGBA, //internal format
142 screenWidth, // width
143 screenHeight, // height
144 0, //border
145 GR_GL_RGBA, //format
146 GR_GL_UNSIGNED_BYTE, // type
halcanary96fcdcc2015-08-27 07:41:13 -0700147 nullptr));
joshualitt74a07db2015-07-01 12:39:07 -0700148
149 // bind framebuffer
150 GrGLuint framebuffer;
151 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
152 GR_GL_CALL(gl, GenFramebuffers(1, &framebuffer));
153 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, framebuffer));
154 GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
155 GR_GL_COLOR_ATTACHMENT0,
156 GR_GL_TEXTURE_2D,
157 texture, 0));
158 GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
159 GR_GL_CALL(gl, Viewport(0, 0, screenWidth, screenHeight));
160 return texture;
161}
162
163
164void GLBench::DumpImage(const GrGLInterface* gl, uint32_t screenWidth, uint32_t screenHeight,
165 const char* filename) {
166 // read back pixels
167 SkAutoTArray<uint32_t> readback(screenWidth * screenHeight);
168 GR_GL_CALL(gl, ReadPixels(0, // x
169 0, // y
170 screenWidth, // width
171 screenHeight, // height
172 GR_GL_RGBA, //format
173 GR_GL_UNSIGNED_BYTE, //type
174 readback.get()));
175
176 // dump png
177 SkBitmap bm;
178 if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(screenWidth, screenHeight))) {
179 SkDebugf("couldn't allocate bitmap\n");
180 return;
181 }
182
183 bm.setPixels(readback.get());
184
185 if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100)) {
186 SkDebugf("------ failed to encode %s\n", filename);
187 remove(filename); // remove any partial file
188 return;
189 }
190}
191
192#endif