blob: f043c952f658219f6a94ab074f355af612c265cd [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 Nicholasf3333c82017-03-31 09:33:41 -040070 SkSL::String glsl;
Ethan Nicholas941e7e22016-12-12 15:33:30 -050071 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
ethannicholas5961bc92016-10-12 06:39:56 -070075 : SkSL::Program::kFragment_Kind,
Ethan Nicholas941e7e22016-12-12 15:33:30 -050076 SkString(sksl),
77 settings);
78 if (!program || !context->compiler()->toGLSL(*program, &glsl)) {
79 SkDebugf("SkSL compilation failed:\n%s\n%s\n", sksl,
ethannicholas5961bc92016-10-12 06:39:56 -070080 context->compiler()->errorText().c_str());
81 }
joshualitt74a07db2015-07-01 12:39:07 -070082 GrGLuint shader;
83 // Create the shader object
84 GR_GL_CALL_RET(gl, shader, CreateShader(type));
85
86 // Load the shader source
ethannicholas5961bc92016-10-12 06:39:56 -070087 const char* glslPtr = glsl.c_str();
88 GR_GL_CALL(gl, ShaderSource(shader, 1, (const char**) &glslPtr, nullptr));
joshualitt74a07db2015-07-01 12:39:07 -070089
90 // Compile the shader
91 GR_GL_CALL(gl, CompileShader(shader));
92
93 // Check for compile time errors
hendrikw894a2e42015-09-08 15:18:56 -070094 GrGLint success = GR_GL_INIT_ZERO;
joshualitt74a07db2015-07-01 12:39:07 -070095 GrGLchar infoLog[512];
96 GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success));
97 if (!success) {
halcanary96fcdcc2015-08-27 07:41:13 -070098 GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, nullptr, infoLog));
joshualitt74a07db2015-07-01 12:39:07 -070099 SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog);
100 }
101
102 return shader;
103}
104
ethannicholas5961bc92016-10-12 06:39:56 -0700105GrGLuint 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);
joshualitt74a07db2015-07-01 12:39:07 -0700110
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
hendrikw894a2e42015-09-08 15:18:56 -0700118 GrGLint success = GR_GL_INIT_ZERO;
joshualitt74a07db2015-07-01 12:39:07 -0700119 GrGLchar infoLog[512];
120 GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success));
121 if (!success) {
halcanary96fcdcc2015-08-27 07:41:13 -0700122 GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, nullptr, infoLog));
joshualitt74a07db2015-07-01 12:39:07 -0700123 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
131GrGLuint GLBench::SetupFramebuffer(const GrGLInterface* gl, int screenWidth, int screenHeight) {
132 //Setup framebuffer
133 GrGLuint texture;
134 GR_GL_CALL(gl, GenTextures(1, &texture));
joshualittb2351682015-10-02 06:49:23 -0700135 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE7));
joshualitt74a07db2015-07-01 12:39:07 -0700136 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
halcanary96fcdcc2015-08-27 07:41:13 -0700149 nullptr));
joshualitt74a07db2015-07-01 12:39:07 -0700150
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
166void 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
Hal Canarydb683012016-11-23 08:55:18 -0700187 if (!sk_tool_utils::EncodeImageToFile(filename, bm, SkEncodedImageFormat::kPNG, 100)) {
joshualitt74a07db2015-07-01 12:39:07 -0700188 SkDebugf("------ failed to encode %s\n", filename);
189 remove(filename); // remove any partial file
190 return;
191 }
192}
193
194#endif