- add sources.
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / test_helper.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/service/test_helper.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_tokenizer.h"
12 #include "gpu/command_buffer/common/types.h"
13 #include "gpu/command_buffer/service/buffer_manager.h"
14 #include "gpu/command_buffer/service/error_state_mock.h"
15 #include "gpu/command_buffer/service/gl_utils.h"
16 #include "gpu/command_buffer/service/gpu_switches.h"
17 #include "gpu/command_buffer/service/program_manager.h"
18 #include "gpu/command_buffer/service/texture_manager.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/gl/gl_mock.h"
21
22 using ::testing::_;
23 using ::testing::DoAll;
24 using ::testing::InSequence;
25 using ::testing::MatcherCast;
26 using ::testing::Pointee;
27 using ::testing::Return;
28 using ::testing::SetArrayArgument;
29 using ::testing::SetArgumentPointee;
30 using ::testing::StrEq;
31 using ::testing::StrictMock;
32
33 namespace gpu {
34 namespace gles2 {
35
36 // GCC requires these declarations, but MSVC requires they not be present
37 #ifndef COMPILER_MSVC
38 const GLuint TestHelper::kServiceBlackTexture2dId;
39 const GLuint TestHelper::kServiceDefaultTexture2dId;
40 const GLuint TestHelper::kServiceBlackTextureCubemapId;
41 const GLuint TestHelper::kServiceDefaultTextureCubemapId;
42 const GLuint TestHelper::kServiceBlackExternalTextureId;
43 const GLuint TestHelper::kServiceDefaultExternalTextureId;
44 const GLuint TestHelper::kServiceBlackRectangleTextureId;
45 const GLuint TestHelper::kServiceDefaultRectangleTextureId;
46
47 const GLint TestHelper::kMaxSamples;
48 const GLint TestHelper::kMaxRenderbufferSize;
49 const GLint TestHelper::kMaxTextureSize;
50 const GLint TestHelper::kMaxCubeMapTextureSize;
51 const GLint TestHelper::kNumVertexAttribs;
52 const GLint TestHelper::kNumTextureUnits;
53 const GLint TestHelper::kMaxTextureImageUnits;
54 const GLint TestHelper::kMaxVertexTextureImageUnits;
55 const GLint TestHelper::kMaxFragmentUniformVectors;
56 const GLint TestHelper::kMaxFragmentUniformComponents;
57 const GLint TestHelper::kMaxVaryingVectors;
58 const GLint TestHelper::kMaxVaryingFloats;
59 const GLint TestHelper::kMaxVertexUniformVectors;
60 const GLint TestHelper::kMaxVertexUniformComponents;
61 #endif
62
63 void TestHelper::SetupTextureInitializationExpectations(
64     ::gfx::MockGLInterface* gl, GLenum target) {
65   InSequence sequence;
66
67   bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
68   bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
69
70   static GLuint texture_2d_ids[] = {
71     kServiceBlackTexture2dId,
72     kServiceDefaultTexture2dId };
73   static GLuint texture_cube_map_ids[] = {
74     kServiceBlackTextureCubemapId,
75     kServiceDefaultTextureCubemapId };
76   static GLuint texture_external_oes_ids[] = {
77     kServiceBlackExternalTextureId,
78     kServiceDefaultExternalTextureId };
79   static GLuint texture_rectangle_arb_ids[] = {
80     kServiceBlackRectangleTextureId,
81     kServiceDefaultRectangleTextureId };
82
83   const GLuint* texture_ids = NULL;
84   switch (target) {
85     case GL_TEXTURE_2D:
86       texture_ids = &texture_2d_ids[0];
87       break;
88     case GL_TEXTURE_CUBE_MAP:
89       texture_ids = &texture_cube_map_ids[0];
90       break;
91     case GL_TEXTURE_EXTERNAL_OES:
92       texture_ids = &texture_external_oes_ids[0];
93       break;
94     case GL_TEXTURE_RECTANGLE_ARB:
95       texture_ids = &texture_rectangle_arb_ids[0];
96       break;
97     default:
98       NOTREACHED();
99   }
100
101   int array_size = 2;
102
103   EXPECT_CALL(*gl, GenTextures(array_size, _))
104       .WillOnce(SetArrayArgument<1>(texture_ids,
105                                     texture_ids + array_size))
106           .RetiresOnSaturation();
107   for (int ii = 0; ii < array_size; ++ii) {
108     EXPECT_CALL(*gl, BindTexture(target, texture_ids[ii]))
109         .Times(1)
110         .RetiresOnSaturation();
111     if (needs_initialization) {
112       if (needs_faces) {
113         static GLenum faces[] = {
114           GL_TEXTURE_CUBE_MAP_POSITIVE_X,
115           GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
116           GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
117           GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
118           GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
119           GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
120         };
121         for (size_t ii = 0; ii < arraysize(faces); ++ii) {
122           EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
123                                       GL_UNSIGNED_BYTE, _))
124               .Times(1)
125               .RetiresOnSaturation();
126         }
127       } else {
128         EXPECT_CALL(*gl, TexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
129                                     GL_UNSIGNED_BYTE, _))
130             .Times(1)
131             .RetiresOnSaturation();
132       }
133     }
134   }
135   EXPECT_CALL(*gl, BindTexture(target, 0))
136       .Times(1)
137       .RetiresOnSaturation();
138 }
139
140 void TestHelper::SetupTextureManagerInitExpectations(
141     ::gfx::MockGLInterface* gl,
142     const char* extensions) {
143   InSequence sequence;
144
145   SetupTextureInitializationExpectations(gl, GL_TEXTURE_2D);
146   SetupTextureInitializationExpectations(gl, GL_TEXTURE_CUBE_MAP);
147
148   bool ext_image_external = false;
149   bool arb_texture_rectangle = false;
150   base::CStringTokenizer t(extensions, extensions + strlen(extensions), " ");
151   while (t.GetNext()) {
152     if (t.token() == "GL_OES_EGL_image_external") {
153       ext_image_external = true;
154       break;
155     }
156     if (t.token() == "GL_ARB_texture_rectangle") {
157       arb_texture_rectangle = true;
158       break;
159     }
160   }
161
162   if (ext_image_external) {
163     SetupTextureInitializationExpectations(gl, GL_TEXTURE_EXTERNAL_OES);
164   }
165   if (arb_texture_rectangle) {
166     SetupTextureInitializationExpectations(gl, GL_TEXTURE_RECTANGLE_ARB);
167   }
168 }
169
170 void TestHelper::SetupTextureDestructionExpectations(
171     ::gfx::MockGLInterface* gl, GLenum target) {
172   GLuint texture_id = 0;
173   switch (target) {
174     case GL_TEXTURE_2D:
175       texture_id = kServiceDefaultTexture2dId;
176       break;
177     case GL_TEXTURE_CUBE_MAP:
178       texture_id = kServiceDefaultTextureCubemapId;
179       break;
180     case GL_TEXTURE_EXTERNAL_OES:
181       texture_id = kServiceDefaultExternalTextureId;
182       break;
183     case GL_TEXTURE_RECTANGLE_ARB:
184       texture_id = kServiceDefaultRectangleTextureId;
185       break;
186     default:
187       NOTREACHED();
188   }
189
190   EXPECT_CALL(*gl, DeleteTextures(1, Pointee(texture_id)))
191       .Times(1)
192       .RetiresOnSaturation();
193 }
194
195 void TestHelper::SetupTextureManagerDestructionExpectations(
196     ::gfx::MockGLInterface* gl,
197     const char* extensions) {
198   SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D);
199   SetupTextureDestructionExpectations(gl, GL_TEXTURE_CUBE_MAP);
200
201   bool ext_image_external = false;
202   bool arb_texture_rectangle = false;
203   base::CStringTokenizer t(extensions, extensions + strlen(extensions), " ");
204   while (t.GetNext()) {
205     if (t.token() == "GL_OES_EGL_image_external") {
206       ext_image_external = true;
207       break;
208     }
209     if (t.token() == "GL_ARB_texture_rectangle") {
210       arb_texture_rectangle = true;
211       break;
212     }
213   }
214
215   if (ext_image_external) {
216     SetupTextureDestructionExpectations(gl, GL_TEXTURE_EXTERNAL_OES);
217   }
218   if (arb_texture_rectangle) {
219     SetupTextureDestructionExpectations(gl, GL_TEXTURE_RECTANGLE_ARB);
220   }
221
222   EXPECT_CALL(*gl, DeleteTextures(4, _))
223       .Times(1)
224       .RetiresOnSaturation();
225 }
226
227 void TestHelper::SetupContextGroupInitExpectations(
228       ::gfx::MockGLInterface* gl,
229       const DisallowedFeatures& disallowed_features,
230       const char* extensions) {
231   InSequence sequence;
232
233   SetupFeatureInfoInitExpectations(gl, extensions);
234
235   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _))
236       .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize))
237       .RetiresOnSaturation();
238   if (strstr(extensions, "GL_EXT_framebuffer_multisample")) {
239     EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _))
240         .WillOnce(SetArgumentPointee<1>(kMaxSamples))
241         .RetiresOnSaturation();
242   }
243   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _))
244       .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs))
245       .RetiresOnSaturation();
246   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, _))
247       .WillOnce(SetArgumentPointee<1>(kNumTextureUnits))
248       .RetiresOnSaturation();
249   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_SIZE, _))
250       .WillOnce(SetArgumentPointee<1>(kMaxTextureSize))
251       .RetiresOnSaturation();
252   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, _))
253       .WillOnce(SetArgumentPointee<1>(kMaxCubeMapTextureSize))
254       .RetiresOnSaturation();
255   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, _))
256       .WillOnce(SetArgumentPointee<1>(kMaxTextureImageUnits))
257       .RetiresOnSaturation();
258   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, _))
259       .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits))
260       .RetiresOnSaturation();
261   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _))
262       .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents))
263       .RetiresOnSaturation();
264   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _))
265       .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats))
266       .RetiresOnSaturation();
267   EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _))
268       .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents))
269       .RetiresOnSaturation();
270
271   SetupTextureManagerInitExpectations(gl, extensions);
272 }
273
274 void TestHelper::SetupFeatureInfoInitExpectations(
275       ::gfx::MockGLInterface* gl, const char* extensions) {
276   SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "");
277 }
278
279 void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
280      ::gfx::MockGLInterface* gl,
281      const char* extensions,
282      const char* version) {
283   InSequence sequence;
284
285   EXPECT_CALL(*gl, GetString(GL_EXTENSIONS))
286       .WillOnce(Return(reinterpret_cast<const uint8*>(extensions)))
287       .RetiresOnSaturation();
288   EXPECT_CALL(*gl, GetString(GL_VERSION))
289       .WillOnce(Return(reinterpret_cast<const uint8*>(version)))
290       .RetiresOnSaturation();
291 }
292
293 void TestHelper::SetupExpectationsForClearingUniforms(
294     ::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms) {
295   for (size_t ii = 0; ii < num_uniforms; ++ii) {
296     const UniformInfo& info = uniforms[ii];
297     switch (info.type) {
298     case GL_FLOAT:
299       EXPECT_CALL(*gl, Uniform1fv(info.real_location, info.size, _))
300           .Times(1)
301           .RetiresOnSaturation();
302       break;
303     case GL_FLOAT_VEC2:
304       EXPECT_CALL(*gl, Uniform2fv(info.real_location, info.size, _))
305           .Times(1)
306           .RetiresOnSaturation();
307       break;
308     case GL_FLOAT_VEC3:
309       EXPECT_CALL(*gl, Uniform3fv(info.real_location, info.size, _))
310           .Times(1)
311           .RetiresOnSaturation();
312       break;
313     case GL_FLOAT_VEC4:
314       EXPECT_CALL(*gl, Uniform4fv(info.real_location, info.size, _))
315           .Times(1)
316           .RetiresOnSaturation();
317       break;
318     case GL_INT:
319     case GL_BOOL:
320     case GL_SAMPLER_2D:
321     case GL_SAMPLER_CUBE:
322     case GL_SAMPLER_EXTERNAL_OES:
323     case GL_SAMPLER_3D_OES:
324     case GL_SAMPLER_2D_RECT_ARB:
325       EXPECT_CALL(*gl, Uniform1iv(info.real_location, info.size, _))
326           .Times(1)
327           .RetiresOnSaturation();
328       break;
329     case GL_INT_VEC2:
330     case GL_BOOL_VEC2:
331       EXPECT_CALL(*gl, Uniform2iv(info.real_location, info.size, _))
332           .Times(1)
333           .RetiresOnSaturation();
334       break;
335     case GL_INT_VEC3:
336     case GL_BOOL_VEC3:
337       EXPECT_CALL(*gl, Uniform3iv(info.real_location, info.size, _))
338           .Times(1)
339           .RetiresOnSaturation();
340       break;
341     case GL_INT_VEC4:
342     case GL_BOOL_VEC4:
343       EXPECT_CALL(*gl, Uniform4iv(info.real_location, info.size, _))
344           .Times(1)
345           .RetiresOnSaturation();
346       break;
347     case GL_FLOAT_MAT2:
348       EXPECT_CALL(*gl, UniformMatrix2fv(
349           info.real_location, info.size, false, _))
350           .Times(1)
351           .RetiresOnSaturation();
352       break;
353     case GL_FLOAT_MAT3:
354       EXPECT_CALL(*gl, UniformMatrix3fv(
355           info.real_location, info.size, false, _))
356           .Times(1)
357           .RetiresOnSaturation();
358       break;
359     case GL_FLOAT_MAT4:
360       EXPECT_CALL(*gl, UniformMatrix4fv(
361           info.real_location, info.size, false, _))
362           .Times(1)
363           .RetiresOnSaturation();
364       break;
365     default:
366       NOTREACHED();
367       break;
368     }
369   }
370 }
371
372 void TestHelper::SetupProgramSuccessExpectations(
373     ::gfx::MockGLInterface* gl,
374     AttribInfo* attribs, size_t num_attribs,
375     UniformInfo* uniforms, size_t num_uniforms,
376     GLuint service_id) {
377   EXPECT_CALL(*gl,
378       GetProgramiv(service_id, GL_LINK_STATUS, _))
379       .WillOnce(SetArgumentPointee<2>(1))
380       .RetiresOnSaturation();
381   EXPECT_CALL(*gl,
382       GetProgramiv(service_id, GL_INFO_LOG_LENGTH, _))
383       .WillOnce(SetArgumentPointee<2>(0))
384       .RetiresOnSaturation();
385   EXPECT_CALL(*gl,
386       GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _))
387       .WillOnce(SetArgumentPointee<2>(num_attribs))
388       .RetiresOnSaturation();
389   size_t max_attrib_len = 0;
390   for (size_t ii = 0; ii < num_attribs; ++ii) {
391     size_t len = strlen(attribs[ii].name) + 1;
392     max_attrib_len = std::max(max_attrib_len, len);
393   }
394   EXPECT_CALL(*gl,
395       GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _))
396       .WillOnce(SetArgumentPointee<2>(max_attrib_len))
397       .RetiresOnSaturation();
398
399   for (size_t ii = 0; ii < num_attribs; ++ii) {
400     const AttribInfo& info = attribs[ii];
401     EXPECT_CALL(*gl,
402         GetActiveAttrib(service_id, ii,
403                         max_attrib_len, _, _, _, _))
404         .WillOnce(DoAll(
405             SetArgumentPointee<3>(strlen(info.name)),
406             SetArgumentPointee<4>(info.size),
407             SetArgumentPointee<5>(info.type),
408             SetArrayArgument<6>(info.name,
409                                 info.name + strlen(info.name) + 1)))
410         .RetiresOnSaturation();
411     if (!ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) {
412       EXPECT_CALL(*gl, GetAttribLocation(service_id, StrEq(info.name)))
413           .WillOnce(Return(info.location))
414           .RetiresOnSaturation();
415     }
416   }
417   EXPECT_CALL(*gl,
418       GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _))
419       .WillOnce(SetArgumentPointee<2>(num_uniforms))
420       .RetiresOnSaturation();
421
422   size_t max_uniform_len = 0;
423   for (size_t ii = 0; ii < num_uniforms; ++ii) {
424     size_t len = strlen(uniforms[ii].name) + 1;
425     max_uniform_len = std::max(max_uniform_len, len);
426   }
427   EXPECT_CALL(*gl,
428       GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _))
429       .WillOnce(SetArgumentPointee<2>(max_uniform_len))
430       .RetiresOnSaturation();
431   for (size_t ii = 0; ii < num_uniforms; ++ii) {
432     const UniformInfo& info = uniforms[ii];
433     EXPECT_CALL(*gl,
434         GetActiveUniform(service_id, ii,
435                          max_uniform_len, _, _, _, _))
436         .WillOnce(DoAll(
437             SetArgumentPointee<3>(strlen(info.name)),
438             SetArgumentPointee<4>(info.size),
439             SetArgumentPointee<5>(info.type),
440             SetArrayArgument<6>(info.name,
441                                 info.name + strlen(info.name) + 1)))
442         .RetiresOnSaturation();
443   }
444
445   for (int pass = 0; pass < 2; ++pass) {
446     for (size_t ii = 0; ii < num_uniforms; ++ii) {
447       const UniformInfo& info = uniforms[ii];
448       if (ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) {
449         continue;
450       }
451       if (pass == 0) {
452         EXPECT_CALL(*gl, GetUniformLocation(service_id, StrEq(info.name)))
453             .WillOnce(Return(info.real_location))
454             .RetiresOnSaturation();
455       }
456       if ((pass == 0 && info.desired_location >= 0) ||
457           (pass == 1 && info.desired_location < 0)) {
458         if (info.size > 1) {
459           std::string base_name = info.name;
460           size_t array_pos = base_name.rfind("[0]");
461           if (base_name.size() > 3 && array_pos == base_name.size() - 3) {
462             base_name = base_name.substr(0, base_name.size() - 3);
463           }
464           for (GLsizei jj = 1; jj < info.size; ++jj) {
465             std::string element_name(
466                 std::string(base_name) + "[" + base::IntToString(jj) + "]");
467             EXPECT_CALL(*gl, GetUniformLocation(
468                 service_id, StrEq(element_name)))
469                 .WillOnce(Return(info.real_location + jj * 2))
470                 .RetiresOnSaturation();
471           }
472         }
473       }
474     }
475   }
476 }
477
478 void TestHelper::SetupShader(
479     ::gfx::MockGLInterface* gl,
480     AttribInfo* attribs, size_t num_attribs,
481     UniformInfo* uniforms, size_t num_uniforms,
482     GLuint service_id) {
483   InSequence s;
484
485   EXPECT_CALL(*gl,
486       LinkProgram(service_id))
487       .Times(1)
488       .RetiresOnSaturation();
489
490   SetupProgramSuccessExpectations(
491       gl, attribs, num_attribs, uniforms, num_uniforms, service_id);
492 }
493
494 void TestHelper::DoBufferData(
495     ::gfx::MockGLInterface* gl, MockErrorState* error_state,
496     BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage,
497     const GLvoid* data, GLenum error) {
498   EXPECT_CALL(*error_state, CopyRealGLErrorsToWrapper(_, _, _))
499       .Times(1)
500       .RetiresOnSaturation();
501   if (manager->IsUsageClientSideArray(usage)) {
502     EXPECT_CALL(*gl, BufferData(
503         buffer->target(), 0, _, usage))
504         .Times(1)
505         .RetiresOnSaturation();
506   } else {
507     EXPECT_CALL(*gl, BufferData(
508         buffer->target(), size, _, usage))
509         .Times(1)
510         .RetiresOnSaturation();
511   }
512   EXPECT_CALL(*error_state, PeekGLError(_, _, _))
513       .WillOnce(Return(error))
514       .RetiresOnSaturation();
515   manager->DoBufferData(error_state, buffer, size, usage, data);
516 }
517
518 void TestHelper::SetTexParameterWithExpectations(
519     ::gfx::MockGLInterface* gl, MockErrorState* error_state,
520     TextureManager* manager, TextureRef* texture_ref,
521     GLenum pname, GLint value, GLenum error) {
522   if (error == GL_NO_ERROR) {
523     if (pname != GL_TEXTURE_POOL_CHROMIUM) {
524       EXPECT_CALL(*gl, TexParameteri(texture_ref->texture()->target(),
525                                      pname, value))
526           .Times(1)
527           .RetiresOnSaturation();
528     }
529   } else if (error == GL_INVALID_ENUM) {
530     EXPECT_CALL(*error_state, SetGLErrorInvalidEnum(_, _, _, value, _))
531         .Times(1)
532         .RetiresOnSaturation();
533   } else {
534     EXPECT_CALL(*error_state, SetGLErrorInvalidParam(_, _, error, _, _, _))
535         .Times(1)
536         .RetiresOnSaturation();
537   }
538   manager->SetParameter("", error_state, texture_ref, pname, value);
539 }
540
541 ScopedGLImplementationSetter::ScopedGLImplementationSetter(
542     gfx::GLImplementation implementation)
543     : old_implementation_(gfx::GetGLImplementation()) {
544   gfx::SetGLImplementation(implementation);
545 }
546
547 ScopedGLImplementationSetter::~ScopedGLImplementationSetter() {
548   gfx::SetGLImplementation(old_implementation_);
549 }
550
551 }  // namespace gles2
552 }  // namespace gpu
553