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/buffer_manager.h"
6 #include "gpu/command_buffer/service/error_state_mock.h"
7 #include "gpu/command_buffer/service/feature_info.h"
8 #include "gpu/command_buffer/service/gpu_service_test.h"
9 #include "gpu/command_buffer/service/mocks.h"
10 #include "gpu/command_buffer/service/test_helper.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gl/gl_mock.h"
13
14 using ::testing::_;
15 using ::testing::Return;
16 using ::testing::StrictMock;
17
18 namespace gpu {
19 namespace gles2 {
20
21 class BufferManagerTestBase : public GpuServiceTest {
22 protected:
SetUpBase(MemoryTracker * memory_tracker,FeatureInfo * feature_info,const char * extensions)23 void SetUpBase(
24 MemoryTracker* memory_tracker,
25 FeatureInfo* feature_info,
26 const char* extensions) {
27 GpuServiceTest::SetUp();
28 if (feature_info) {
29 TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions);
30 feature_info->Initialize();
31 }
32 error_state_.reset(new MockErrorState());
33 manager_.reset(new BufferManager(memory_tracker, feature_info));
34 }
35
TearDown()36 virtual void TearDown() {
37 manager_->Destroy(false);
38 manager_.reset();
39 error_state_.reset();
40 GpuServiceTest::TearDown();
41 }
42
GetTarget(const Buffer * buffer) const43 GLenum GetTarget(const Buffer* buffer) const {
44 return buffer->target();
45 }
46
DoBufferData(Buffer * buffer,GLsizeiptr size,GLenum usage,const GLvoid * data,GLenum error)47 void DoBufferData(
48 Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data,
49 GLenum error) {
50 TestHelper::DoBufferData(
51 gl_.get(), error_state_.get(), manager_.get(),
52 buffer, size, usage, data, error);
53 }
54
DoBufferSubData(Buffer * buffer,GLintptr offset,GLsizeiptr size,const GLvoid * data)55 bool DoBufferSubData(
56 Buffer* buffer, GLintptr offset, GLsizeiptr size,
57 const GLvoid* data) {
58 bool success = true;
59 if (!buffer->CheckRange(offset, size)) {
60 EXPECT_CALL(*error_state_, SetGLError(_, _, GL_INVALID_VALUE, _, _))
61 .Times(1)
62 .RetiresOnSaturation();
63 success = false;
64 } else if (!buffer->IsClientSideArray()) {
65 EXPECT_CALL(*gl_, BufferSubData(
66 buffer->target(), offset, size, _))
67 .Times(1)
68 .RetiresOnSaturation();
69 }
70 manager_->DoBufferSubData(
71 error_state_.get(), buffer, offset, size, data);
72 return success;
73 }
74
75 scoped_ptr<BufferManager> manager_;
76 scoped_ptr<MockErrorState> error_state_;
77 };
78
79 class BufferManagerTest : public BufferManagerTestBase {
80 protected:
SetUp()81 virtual void SetUp() {
82 SetUpBase(NULL, NULL, "");
83 }
84 };
85
86 class BufferManagerMemoryTrackerTest : public BufferManagerTestBase {
87 protected:
SetUp()88 virtual void SetUp() {
89 mock_memory_tracker_ = new StrictMock<MockMemoryTracker>();
90 SetUpBase(mock_memory_tracker_.get(), NULL, "");
91 }
92
93 scoped_refptr<MockMemoryTracker> mock_memory_tracker_;
94 };
95
96 class BufferManagerClientSideArraysTest : public BufferManagerTestBase {
97 protected:
SetUp()98 virtual void SetUp() {
99 feature_info_ = new FeatureInfo();
100 feature_info_->workarounds_.use_client_side_arrays_for_stream_buffers =
101 true;
102 SetUpBase(NULL, feature_info_.get(), "");
103 }
104
105 scoped_refptr<FeatureInfo> feature_info_;
106 };
107
108 #define EXPECT_MEMORY_ALLOCATION_CHANGE(old_size, new_size, pool) \
109 EXPECT_CALL(*mock_memory_tracker_.get(), \
110 TrackMemoryAllocatedChange(old_size, new_size, pool)) \
111 .Times(1).RetiresOnSaturation()
112
TEST_F(BufferManagerTest,Basic)113 TEST_F(BufferManagerTest, Basic) {
114 const GLuint kClientBuffer1Id = 1;
115 const GLuint kServiceBuffer1Id = 11;
116 const GLsizeiptr kBuffer1Size = 123;
117 const GLuint kClientBuffer2Id = 2;
118 // Check we can create buffer.
119 manager_->CreateBuffer(kClientBuffer1Id, kServiceBuffer1Id);
120 // Check buffer got created.
121 Buffer* buffer1 = manager_->GetBuffer(kClientBuffer1Id);
122 ASSERT_TRUE(buffer1 != NULL);
123 EXPECT_EQ(0u, GetTarget(buffer1));
124 EXPECT_EQ(0, buffer1->size());
125 EXPECT_EQ(static_cast<GLenum>(GL_STATIC_DRAW), buffer1->usage());
126 EXPECT_FALSE(buffer1->IsDeleted());
127 EXPECT_FALSE(buffer1->IsClientSideArray());
128 EXPECT_EQ(kServiceBuffer1Id, buffer1->service_id());
129 GLuint client_id = 0;
130 EXPECT_TRUE(manager_->GetClientId(buffer1->service_id(), &client_id));
131 EXPECT_EQ(kClientBuffer1Id, client_id);
132 manager_->SetTarget(buffer1, GL_ELEMENT_ARRAY_BUFFER);
133 EXPECT_EQ(static_cast<GLenum>(GL_ELEMENT_ARRAY_BUFFER), GetTarget(buffer1));
134 // Check we and set its size.
135 DoBufferData(buffer1, kBuffer1Size, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR);
136 EXPECT_EQ(kBuffer1Size, buffer1->size());
137 EXPECT_EQ(static_cast<GLenum>(GL_DYNAMIC_DRAW), buffer1->usage());
138 // Check we get nothing for a non-existent buffer.
139 EXPECT_TRUE(manager_->GetBuffer(kClientBuffer2Id) == NULL);
140 // Check trying to a remove non-existent buffers does not crash.
141 manager_->RemoveBuffer(kClientBuffer2Id);
142 // Check that it gets deleted when the last reference is released.
143 EXPECT_CALL(*gl_, DeleteBuffersARB(1, ::testing::Pointee(kServiceBuffer1Id)))
144 .Times(1)
145 .RetiresOnSaturation();
146 // Check we can't get the buffer after we remove it.
147 manager_->RemoveBuffer(kClientBuffer1Id);
148 EXPECT_TRUE(manager_->GetBuffer(kClientBuffer1Id) == NULL);
149 }
150
TEST_F(BufferManagerMemoryTrackerTest,Basic)151 TEST_F(BufferManagerMemoryTrackerTest, Basic) {
152 const GLuint kClientBuffer1Id = 1;
153 const GLuint kServiceBuffer1Id = 11;
154 const GLsizeiptr kBuffer1Size1 = 123;
155 const GLsizeiptr kBuffer1Size2 = 456;
156 // Check we can create buffer.
157 EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kManaged);
158 manager_->CreateBuffer(kClientBuffer1Id, kServiceBuffer1Id);
159 // Check buffer got created.
160 Buffer* buffer1 = manager_->GetBuffer(kClientBuffer1Id);
161 ASSERT_TRUE(buffer1 != NULL);
162 manager_->SetTarget(buffer1, GL_ELEMENT_ARRAY_BUFFER);
163 // Check we and set its size.
164 EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size1, MemoryTracker::kManaged);
165 DoBufferData(buffer1, kBuffer1Size1, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR);
166 EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size1, 0, MemoryTracker::kManaged);
167 EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size2, MemoryTracker::kManaged);
168 DoBufferData(buffer1, kBuffer1Size2, GL_DYNAMIC_DRAW, NULL, GL_NO_ERROR);
169 // On delete it will get freed.
170 EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size2, 0, MemoryTracker::kManaged);
171 }
172
TEST_F(BufferManagerTest,Destroy)173 TEST_F(BufferManagerTest, Destroy) {
174 const GLuint kClient1Id = 1;
175 const GLuint kService1Id = 11;
176 // Check we can create buffer.
177 manager_->CreateBuffer(kClient1Id, kService1Id);
178 // Check buffer got created.
179 Buffer* buffer1 = manager_->GetBuffer(kClient1Id);
180 ASSERT_TRUE(buffer1 != NULL);
181 EXPECT_CALL(*gl_, DeleteBuffersARB(1, ::testing::Pointee(kService1Id)))
182 .Times(1)
183 .RetiresOnSaturation();
184 manager_->Destroy(true);
185 // Check the resources were released.
186 buffer1 = manager_->GetBuffer(kClient1Id);
187 ASSERT_TRUE(buffer1 == NULL);
188 }
189
TEST_F(BufferManagerTest,DoBufferSubData)190 TEST_F(BufferManagerTest, DoBufferSubData) {
191 const GLuint kClientBufferId = 1;
192 const GLuint kServiceBufferId = 11;
193 const uint8 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
194 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
195 Buffer* buffer = manager_->GetBuffer(kClientBufferId);
196 ASSERT_TRUE(buffer != NULL);
197 manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER);
198 DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
199 EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data));
200 EXPECT_TRUE(DoBufferSubData(buffer, sizeof(data), 0, data));
201 EXPECT_FALSE(DoBufferSubData(buffer, sizeof(data), 1, data));
202 EXPECT_FALSE(DoBufferSubData(buffer, 0, sizeof(data) + 1, data));
203 EXPECT_FALSE(DoBufferSubData(buffer, -1, sizeof(data), data));
204 EXPECT_FALSE(DoBufferSubData(buffer, 0, -1, data));
205 DoBufferData(buffer, 1, GL_STATIC_DRAW, NULL, GL_NO_ERROR);
206 const int size = 0x20000;
207 scoped_ptr<uint8[]> temp(new uint8[size]);
208 EXPECT_FALSE(DoBufferSubData(buffer, 0 - size, size, temp.get()));
209 EXPECT_FALSE(DoBufferSubData(buffer, 1, size / 2, temp.get()));
210 }
211
TEST_F(BufferManagerTest,GetRange)212 TEST_F(BufferManagerTest, GetRange) {
213 const GLuint kClientBufferId = 1;
214 const GLuint kServiceBufferId = 11;
215 const uint8 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
216 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
217 Buffer* buffer = manager_->GetBuffer(kClientBufferId);
218 ASSERT_TRUE(buffer != NULL);
219 manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER);
220 DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
221 const char* buf =
222 static_cast<const char*>(buffer->GetRange(0, sizeof(data)));
223 ASSERT_TRUE(buf != NULL);
224 const char* buf1 =
225 static_cast<const char*>(buffer->GetRange(1, sizeof(data) - 1));
226 EXPECT_EQ(buf + 1, buf1);
227 EXPECT_TRUE(buffer->GetRange(sizeof(data), 1) == NULL);
228 EXPECT_TRUE(buffer->GetRange(0, sizeof(data) + 1) == NULL);
229 EXPECT_TRUE(buffer->GetRange(-1, sizeof(data)) == NULL);
230 EXPECT_TRUE(buffer->GetRange(-0, -1) == NULL);
231 const int size = 0x20000;
232 DoBufferData(buffer, size / 2, GL_STATIC_DRAW, NULL, GL_NO_ERROR);
233 EXPECT_TRUE(buffer->GetRange(0 - size, size) == NULL);
234 EXPECT_TRUE(buffer->GetRange(1, size / 2) == NULL);
235 }
236
TEST_F(BufferManagerTest,GetMaxValueForRangeUint8)237 TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) {
238 const GLuint kClientBufferId = 1;
239 const GLuint kServiceBufferId = 11;
240 const uint8 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
241 const uint8 new_data[] = {100, 120, 110};
242 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
243 Buffer* buffer = manager_->GetBuffer(kClientBufferId);
244 ASSERT_TRUE(buffer != NULL);
245 manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER);
246 DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
247 EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data));
248 GLuint max_value;
249 // Check entire range succeeds.
250 EXPECT_TRUE(buffer->GetMaxValueForRange(
251 0, 10, GL_UNSIGNED_BYTE, &max_value));
252 EXPECT_EQ(10u, max_value);
253 // Check sub range succeeds.
254 EXPECT_TRUE(buffer->GetMaxValueForRange(
255 4, 3, GL_UNSIGNED_BYTE, &max_value));
256 EXPECT_EQ(6u, max_value);
257 // Check changing sub range succeeds.
258 EXPECT_TRUE(DoBufferSubData(buffer, 4, sizeof(new_data), new_data));
259 EXPECT_TRUE(buffer->GetMaxValueForRange(
260 4, 3, GL_UNSIGNED_BYTE, &max_value));
261 EXPECT_EQ(120u, max_value);
262 max_value = 0;
263 EXPECT_TRUE(buffer->GetMaxValueForRange(
264 0, 10, GL_UNSIGNED_BYTE, &max_value));
265 EXPECT_EQ(120u, max_value);
266 // Check out of range fails.
267 EXPECT_FALSE(buffer->GetMaxValueForRange(
268 0, 11, GL_UNSIGNED_BYTE, &max_value));
269 EXPECT_FALSE(buffer->GetMaxValueForRange(
270 10, 1, GL_UNSIGNED_BYTE, &max_value));
271 }
272
TEST_F(BufferManagerTest,GetMaxValueForRangeUint16)273 TEST_F(BufferManagerTest, GetMaxValueForRangeUint16) {
274 const GLuint kClientBufferId = 1;
275 const GLuint kServiceBufferId = 11;
276 const uint16 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
277 const uint16 new_data[] = {100, 120, 110};
278 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
279 Buffer* buffer = manager_->GetBuffer(kClientBufferId);
280 ASSERT_TRUE(buffer != NULL);
281 manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER);
282 DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
283 EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data));
284 GLuint max_value;
285 // Check entire range succeeds.
286 EXPECT_TRUE(buffer->GetMaxValueForRange(
287 0, 10, GL_UNSIGNED_SHORT, &max_value));
288 EXPECT_EQ(10u, max_value);
289 // Check odd offset fails for GL_UNSIGNED_SHORT.
290 EXPECT_FALSE(buffer->GetMaxValueForRange(
291 1, 10, GL_UNSIGNED_SHORT, &max_value));
292 // Check sub range succeeds.
293 EXPECT_TRUE(buffer->GetMaxValueForRange(
294 8, 3, GL_UNSIGNED_SHORT, &max_value));
295 EXPECT_EQ(6u, max_value);
296 // Check changing sub range succeeds.
297 EXPECT_TRUE(DoBufferSubData(buffer, 8, sizeof(new_data), new_data));
298 EXPECT_TRUE(buffer->GetMaxValueForRange(
299 8, 3, GL_UNSIGNED_SHORT, &max_value));
300 EXPECT_EQ(120u, max_value);
301 max_value = 0;
302 EXPECT_TRUE(buffer->GetMaxValueForRange(
303 0, 10, GL_UNSIGNED_SHORT, &max_value));
304 EXPECT_EQ(120u, max_value);
305 // Check out of range fails.
306 EXPECT_FALSE(buffer->GetMaxValueForRange(
307 0, 11, GL_UNSIGNED_SHORT, &max_value));
308 EXPECT_FALSE(buffer->GetMaxValueForRange(
309 20, 1, GL_UNSIGNED_SHORT, &max_value));
310 }
311
TEST_F(BufferManagerTest,GetMaxValueForRangeUint32)312 TEST_F(BufferManagerTest, GetMaxValueForRangeUint32) {
313 const GLuint kClientBufferId = 1;
314 const GLuint kServiceBufferId = 11;
315 const uint32 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
316 const uint32 new_data[] = {100, 120, 110};
317 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
318 Buffer* buffer = manager_->GetBuffer(kClientBufferId);
319 ASSERT_TRUE(buffer != NULL);
320 manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER);
321 DoBufferData(buffer, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
322 EXPECT_TRUE(DoBufferSubData(buffer, 0, sizeof(data), data));
323 GLuint max_value;
324 // Check entire range succeeds.
325 EXPECT_TRUE(
326 buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
327 EXPECT_EQ(10u, max_value);
328 // Check non aligned offsets fails for GL_UNSIGNED_INT.
329 EXPECT_FALSE(
330 buffer->GetMaxValueForRange(1, 10, GL_UNSIGNED_INT, &max_value));
331 EXPECT_FALSE(
332 buffer->GetMaxValueForRange(2, 10, GL_UNSIGNED_INT, &max_value));
333 EXPECT_FALSE(
334 buffer->GetMaxValueForRange(3, 10, GL_UNSIGNED_INT, &max_value));
335 // Check sub range succeeds.
336 EXPECT_TRUE(buffer->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT, &max_value));
337 EXPECT_EQ(6u, max_value);
338 // Check changing sub range succeeds.
339 EXPECT_TRUE(DoBufferSubData(buffer, 16, sizeof(new_data), new_data));
340 EXPECT_TRUE(buffer->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT, &max_value));
341 EXPECT_EQ(120u, max_value);
342 max_value = 0;
343 EXPECT_TRUE(buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
344 EXPECT_EQ(120u, max_value);
345 // Check out of range fails.
346 EXPECT_FALSE(
347 buffer->GetMaxValueForRange(0, 11, GL_UNSIGNED_INT, &max_value));
348 EXPECT_FALSE(
349 buffer->GetMaxValueForRange(40, 1, GL_UNSIGNED_INT, &max_value));
350 }
351
TEST_F(BufferManagerTest,UseDeletedBuffer)352 TEST_F(BufferManagerTest, UseDeletedBuffer) {
353 const GLuint kClientBufferId = 1;
354 const GLuint kServiceBufferId = 11;
355 const uint32 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
356 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
357 scoped_refptr<Buffer> buffer = manager_->GetBuffer(kClientBufferId);
358 ASSERT_TRUE(buffer.get() != NULL);
359 manager_->SetTarget(buffer.get(), GL_ARRAY_BUFFER);
360 // Remove buffer
361 manager_->RemoveBuffer(kClientBufferId);
362 // Use it after removing
363 DoBufferData(buffer.get(), sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
364 // Check that it gets deleted when the last reference is released.
365 EXPECT_CALL(*gl_, DeleteBuffersARB(1, ::testing::Pointee(kServiceBufferId)))
366 .Times(1)
367 .RetiresOnSaturation();
368 buffer = NULL;
369 }
370
371 // Test buffers get shadowed when they are supposed to be.
TEST_F(BufferManagerClientSideArraysTest,StreamBuffersAreShadowed)372 TEST_F(BufferManagerClientSideArraysTest, StreamBuffersAreShadowed) {
373 const GLuint kClientBufferId = 1;
374 const GLuint kServiceBufferId = 11;
375 static const uint32 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
376 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
377 Buffer* buffer = manager_->GetBuffer(kClientBufferId);
378 ASSERT_TRUE(buffer != NULL);
379 manager_->SetTarget(buffer, GL_ARRAY_BUFFER);
380 DoBufferData(buffer, sizeof(data), GL_STREAM_DRAW, data, GL_NO_ERROR);
381 EXPECT_TRUE(buffer->IsClientSideArray());
382 EXPECT_EQ(0, memcmp(data, buffer->GetRange(0, sizeof(data)), sizeof(data)));
383 DoBufferData(buffer, sizeof(data), GL_DYNAMIC_DRAW, data, GL_NO_ERROR);
384 EXPECT_FALSE(buffer->IsClientSideArray());
385 }
386
TEST_F(BufferManagerTest,MaxValueCacheClearedCorrectly)387 TEST_F(BufferManagerTest, MaxValueCacheClearedCorrectly) {
388 const GLuint kClientBufferId = 1;
389 const GLuint kServiceBufferId = 11;
390 const uint32 data1[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
391 const uint32 data2[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
392 const uint32 data3[] = {30, 29, 28};
393 manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
394 Buffer* buffer = manager_->GetBuffer(kClientBufferId);
395 ASSERT_TRUE(buffer != NULL);
396 manager_->SetTarget(buffer, GL_ELEMENT_ARRAY_BUFFER);
397 GLuint max_value;
398 // Load the buffer with some initial data, and then get the maximum value for
399 // a range, which has the side effect of caching it.
400 DoBufferData(buffer, sizeof(data1), GL_STATIC_DRAW, data1, GL_NO_ERROR);
401 EXPECT_TRUE(
402 buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
403 EXPECT_EQ(10u, max_value);
404 // Check that any cached values are invalidated if the buffer is reloaded
405 // with the same amount of data (but different content)
406 ASSERT_EQ(sizeof(data2), sizeof(data1));
407 DoBufferData(buffer, sizeof(data2), GL_STATIC_DRAW, data2, GL_NO_ERROR);
408 EXPECT_TRUE(
409 buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
410 EXPECT_EQ(20u, max_value);
411 // Check that any cached values are invalidated if the buffer is reloaded
412 // with entirely different content.
413 ASSERT_NE(sizeof(data3), sizeof(data1));
414 DoBufferData(buffer, sizeof(data3), GL_STATIC_DRAW, data3, GL_NO_ERROR);
415 EXPECT_TRUE(
416 buffer->GetMaxValueForRange(0, 3, GL_UNSIGNED_INT, &max_value));
417 EXPECT_EQ(30u, max_value);
418 }
419
420 } // namespace gles2
421 } // namespace gpu
422
423
424