blob: 38205e29f0d5939cbcf542c0c188f6fab6166f5a [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>
17
Hal Canarydb683012016-11-23 08:55:18 -070018#include "sk_tool_utils.h"
19
joshualitt74a07db2015-07-01 12:39:07 -070020const GrGLContext* GLBench::getGLContext(SkCanvas* canvas) {
21 // This bench exclusively tests GL calls directly
halcanary96fcdcc2015-08-27 07:41:13 -070022 if (nullptr == canvas->getGrContext()) {
23 return nullptr;
joshualitt74a07db2015-07-01 12:39:07 -070024 }
25 GrContext* context = canvas->getGrContext();
jvanverth672bb7f2015-07-13 07:19:57 -070026 GrGpu* gpu = context->getGpu();
27 if (!gpu) {
28 SkDebugf("Couldn't get Gr gpu.");
halcanary96fcdcc2015-08-27 07:41:13 -070029 return nullptr;
joshualitt74a07db2015-07-01 12:39:07 -070030 }
31
jvanverth672bb7f2015-07-13 07:19:57 -070032 const GrGLContext* ctx = gpu->glContextForTesting();
joshualitt74a07db2015-07-01 12:39:07 -070033 if (!ctx) {
34 SkDebugf("Couldn't get an interface\n");
halcanary96fcdcc2015-08-27 07:41:13 -070035 return nullptr;
joshualitt74a07db2015-07-01 12:39:07 -070036 }
37
38 return this->onGetGLContext(ctx);
39}
40
joshualitt8a6697a2015-09-30 12:11:07 -070041void GLBench::onPreDraw(SkCanvas* canvas) {
joshualitt74a07db2015-07-01 12:39:07 -070042 // 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
joshualitt8a6697a2015-09-30 12:11:07 -070050void GLBench::onPostDraw(SkCanvas* canvas) {
joshualitt74a07db2015-07-01 12:39:07 -070051 // 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
mtkleina1ebeb22015-10-01 09:43:39 -070059void GLBench::onDraw(int loops, SkCanvas* canvas) {
joshualitt74a07db2015-07-01 12:39:07 -070060 const GrGLContext* ctx = this->getGLContext(canvas);
61 if (!ctx) {
62 return;
63 }
64 this->glDraw(loops, ctx);
brianosman393c2ff2016-05-11 08:49:59 -070065 canvas->getGrContext()->resetContext();
joshualitt74a07db2015-07-01 12:39:07 -070066}
67
ethannicholas5961bc92016-10-12 06:39:56 -070068GrGLuint GLBench::CompileShader(const GrGLContext* context, const char* sksl, GrGLenum type) {
69 const GrGLInterface* gl = context->interface();
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050070 SkString glsl;
ethannicholas5961bc92016-10-12 06:39:56 -070071 bool result = context->compiler()->toGLSL(type == GR_GL_VERTEX_SHADER
72 ? SkSL::Program::kVertex_Kind
73 : SkSL::Program::kFragment_Kind,
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050074 SkString(sksl),
Brian Salomon1edc5b92016-11-29 13:43:46 -050075 *context->caps()->shaderCaps(),
ethannicholas5961bc92016-10-12 06:39:56 -070076 &glsl);
77 if (!result) {
78 SkDebugf("SkSL compilation failed:\n%s\n%s\n", sksl,
79 context->compiler()->errorText().c_str());
80 }
joshualitt74a07db2015-07-01 12:39:07 -070081 GrGLuint shader;
82 // Create the shader object
83 GR_GL_CALL_RET(gl, shader, CreateShader(type));
84
85 // Load the shader source
ethannicholas5961bc92016-10-12 06:39:56 -070086 const char* glslPtr = glsl.c_str();
87 GR_GL_CALL(gl, ShaderSource(shader, 1, (const char**) &glslPtr, nullptr));
joshualitt74a07db2015-07-01 12:39:07 -070088
89 // Compile the shader
90 GR_GL_CALL(gl, CompileShader(shader));
91
92 // Check for compile time errors
hendrikw894a2e42015-09-08 15:18:56 -070093 GrGLint success = GR_GL_INIT_ZERO;
joshualitt74a07db2015-07-01 12:39:07 -070094 GrGLchar infoLog[512];
95 GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success));
96 if (!success) {
halcanary96fcdcc2015-08-27 07:41:13 -070097 GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, nullptr, infoLog));
joshualitt74a07db2015-07-01 12:39:07 -070098 SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog);
99 }
100
101 return shader;
102}
103
ethannicholas5961bc92016-10-12 06:39:56 -0700104GrGLuint GLBench::CreateProgram(const GrGLContext* context, const char* vshader,
105 const char* fshader) {
106 const GrGLInterface* gl = context->interface();
107 GrGLuint vertexShader = CompileShader(context, vshader, GR_GL_VERTEX_SHADER);
108 GrGLuint fragmentShader = CompileShader(context, fshader, GR_GL_FRAGMENT_SHADER);
joshualitt74a07db2015-07-01 12:39:07 -0700109
110 GrGLuint shaderProgram;
111 GR_GL_CALL_RET(gl, shaderProgram, CreateProgram());
112 GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader));
113 GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader));
114 GR_GL_CALL(gl, LinkProgram(shaderProgram));
115
116 // Check for linking errors
hendrikw894a2e42015-09-08 15:18:56 -0700117 GrGLint success = GR_GL_INIT_ZERO;
joshualitt74a07db2015-07-01 12:39:07 -0700118 GrGLchar infoLog[512];
119 GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success));
120 if (!success) {
halcanary96fcdcc2015-08-27 07:41:13 -0700121 GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, nullptr, infoLog));
joshualitt74a07db2015-07-01 12:39:07 -0700122 SkDebugf("Linker Error: %s\n", infoLog);
123 }
124 GR_GL_CALL(gl, DeleteShader(vertexShader));
125 GR_GL_CALL(gl, DeleteShader(fragmentShader));
126
127 return shaderProgram;
128}
129
130GrGLuint GLBench::SetupFramebuffer(const GrGLInterface* gl, int screenWidth, int screenHeight) {
131 //Setup framebuffer
132 GrGLuint texture;
133 GR_GL_CALL(gl, GenTextures(1, &texture));
joshualittb2351682015-10-02 06:49:23 -0700134 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE7));
joshualitt74a07db2015-07-01 12:39:07 -0700135 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texture));
136 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
137 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
138 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
139 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
140 GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D,
141 0, //level
142 GR_GL_RGBA, //internal format
143 screenWidth, // width
144 screenHeight, // height
145 0, //border
146 GR_GL_RGBA, //format
147 GR_GL_UNSIGNED_BYTE, // type
halcanary96fcdcc2015-08-27 07:41:13 -0700148 nullptr));
joshualitt74a07db2015-07-01 12:39:07 -0700149
150 // bind framebuffer
151 GrGLuint framebuffer;
152 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
153 GR_GL_CALL(gl, GenFramebuffers(1, &framebuffer));
154 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, framebuffer));
155 GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
156 GR_GL_COLOR_ATTACHMENT0,
157 GR_GL_TEXTURE_2D,
158 texture, 0));
159 GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
160 GR_GL_CALL(gl, Viewport(0, 0, screenWidth, screenHeight));
161 return texture;
162}
163
164
165void GLBench::DumpImage(const GrGLInterface* gl, uint32_t screenWidth, uint32_t screenHeight,
166 const char* filename) {
167 // read back pixels
168 SkAutoTArray<uint32_t> readback(screenWidth * screenHeight);
169 GR_GL_CALL(gl, ReadPixels(0, // x
170 0, // y
171 screenWidth, // width
172 screenHeight, // height
173 GR_GL_RGBA, //format
174 GR_GL_UNSIGNED_BYTE, //type
175 readback.get()));
176
177 // dump png
178 SkBitmap bm;
179 if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(screenWidth, screenHeight))) {
180 SkDebugf("couldn't allocate bitmap\n");
181 return;
182 }
183
184 bm.setPixels(readback.get());
185
Hal Canarydb683012016-11-23 08:55:18 -0700186 if (!sk_tool_utils::EncodeImageToFile(filename, bm, SkEncodedImageFormat::kPNG, 100)) {
joshualitt74a07db2015-07-01 12:39:07 -0700187 SkDebugf("------ failed to encode %s\n", filename);
188 remove(filename); // remove any partial file
189 return;
190 }
191}
192
193#endif