OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // A class to emluate GLES2 over command buffers. | 5 // A class to emluate GLES2 over command buffers. |
6 | 6 |
7 #include "gpu/command_buffer/client/gles2_implementation.h" | 7 #include "gpu/command_buffer/client/gles2_implementation.h" |
8 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 8 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
9 | 9 |
10 namespace gpu { | 10 namespace gpu { |
(...skipping 11 matching lines...) Expand all Loading... |
22 GLES2Implementation::GLES2Implementation( | 22 GLES2Implementation::GLES2Implementation( |
23 GLES2CmdHelper* helper, | 23 GLES2CmdHelper* helper, |
24 size_t transfer_buffer_size, | 24 size_t transfer_buffer_size, |
25 void* transfer_buffer, | 25 void* transfer_buffer, |
26 int32 transfer_buffer_id) | 26 int32 transfer_buffer_id) |
27 : util_(0), // TODO(gman): Get real number of compressed texture formats. | 27 : util_(0), // TODO(gman): Get real number of compressed texture formats. |
28 helper_(helper), | 28 helper_(helper), |
29 transfer_buffer_(transfer_buffer_size, helper, transfer_buffer), | 29 transfer_buffer_(transfer_buffer_size, helper, transfer_buffer), |
30 transfer_buffer_id_(transfer_buffer_id), | 30 transfer_buffer_id_(transfer_buffer_id), |
31 pack_alignment_(4), | 31 pack_alignment_(4), |
32 unpack_alignment_(4) { | 32 unpack_alignment_(4), |
| 33 error_bits_(0) { |
33 // Eat 1 id so we start at 1 instead of 0. | 34 // Eat 1 id so we start at 1 instead of 0. |
34 GLuint eat; | 35 GLuint eat; |
35 MakeIds(1, &eat); | 36 MakeIds(1, &eat); |
36 // Allocate space for simple GL results. | 37 // Allocate space for simple GL results. |
37 result_buffer_ = transfer_buffer_.Alloc(kMaxSizeOfSimpleResult); | 38 result_buffer_ = transfer_buffer_.Alloc(kMaxSizeOfSimpleResult); |
38 result_shm_offset_ = transfer_buffer_.GetOffset(result_buffer_); | 39 result_shm_offset_ = transfer_buffer_.GetOffset(result_buffer_); |
39 } | 40 } |
40 | 41 |
41 GLES2Implementation::~GLES2Implementation() { | 42 GLES2Implementation::~GLES2Implementation() { |
42 transfer_buffer_.Free(result_buffer_); | 43 transfer_buffer_.Free(result_buffer_); |
43 } | 44 } |
44 | 45 |
45 void GLES2Implementation::MakeIds(GLsizei n, GLuint* ids) { | 46 void GLES2Implementation::MakeIds(GLsizei n, GLuint* ids) { |
46 for (GLsizei ii = 0; ii < n; ++ii) { | 47 for (GLsizei ii = 0; ii < n; ++ii) { |
47 ids[ii] = id_allocator_.AllocateID(); | 48 ids[ii] = id_allocator_.AllocateID(); |
48 } | 49 } |
49 } | 50 } |
50 | 51 |
51 void GLES2Implementation::FreeIds(GLsizei n, const GLuint* ids) { | 52 void GLES2Implementation::FreeIds(GLsizei n, const GLuint* ids) { |
52 for (GLsizei ii = 0; ii < n; ++ii) { | 53 for (GLsizei ii = 0; ii < n; ++ii) { |
53 id_allocator_.FreeID(ids[ii]); | 54 id_allocator_.FreeID(ids[ii]); |
54 } | 55 } |
55 } | 56 } |
56 | 57 |
57 void GLES2Implementation::WaitForCmd() { | 58 void GLES2Implementation::WaitForCmd() { |
58 helper_->CommandBufferHelper::Finish(); | 59 helper_->CommandBufferHelper::Finish(); |
59 } | 60 } |
60 | 61 |
| 62 GLenum GLES2Implementation::GetError() { |
| 63 return GetGLError(); |
| 64 } |
| 65 |
| 66 GLenum GLES2Implementation::GetGLError() { |
| 67 // Check the GL error first, then our wrapped error. |
| 68 typedef gles2::GetError::Result Result; |
| 69 Result* result = GetResultAs<Result*>(); |
| 70 *result = GL_NO_ERROR; |
| 71 helper_->GetError(result_shm_id(), result_shm_offset()); |
| 72 WaitForCmd(); |
| 73 GLenum error = *result; |
| 74 if (error == GL_NO_ERROR && error_bits_ != 0) { |
| 75 for (uint32 mask = 1; mask != 0; mask = mask << 1) { |
| 76 if ((error_bits_ & mask) != 0) { |
| 77 error = GLES2Util::GLErrorBitToGLError(mask); |
| 78 break; |
| 79 } |
| 80 } |
| 81 } |
| 82 |
| 83 if (error != GL_NO_ERROR) { |
| 84 // There was an error, clear the corresponding wrapped error. |
| 85 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error); |
| 86 } |
| 87 return error; |
| 88 } |
| 89 |
| 90 void GLES2Implementation::SetGLError(GLenum error) { |
| 91 error_bits_ |= GLES2Util::GLErrorToErrorBit(error); |
| 92 } |
| 93 |
61 void GLES2Implementation::GetBucketContents(uint32 bucket_id, | 94 void GLES2Implementation::GetBucketContents(uint32 bucket_id, |
62 std::vector<int8>* data) { | 95 std::vector<int8>* data) { |
63 DCHECK(data); | 96 DCHECK(data); |
| 97 typedef cmd::GetBucketSize::Result Result; |
| 98 Result* result = GetResultAs<Result*>(); |
| 99 *result = 0; |
64 helper_->GetBucketSize(bucket_id, result_shm_id(), result_shm_offset()); | 100 helper_->GetBucketSize(bucket_id, result_shm_id(), result_shm_offset()); |
65 WaitForCmd(); | 101 WaitForCmd(); |
66 uint32 size = GetResultAs<cmd::GetBucketSize::Result>(); | 102 uint32 size = *result; |
67 data->resize(size); | 103 data->resize(size); |
68 if (size > 0u) { | 104 if (size > 0u) { |
69 uint32 max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); | 105 uint32 max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); |
70 uint32 offset = 0; | 106 uint32 offset = 0; |
71 while (size) { | 107 while (size) { |
72 uint32 part_size = std::min(max_size, size); | 108 uint32 part_size = std::min(max_size, size); |
73 void* buffer = transfer_buffer_.Alloc(part_size); | 109 void* buffer = transfer_buffer_.Alloc(part_size); |
74 helper_->GetBucketData( | 110 helper_->GetBucketData( |
75 bucket_id, offset, part_size, | 111 bucket_id, offset, part_size, |
76 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); | 112 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); |
(...skipping 24 matching lines...) Expand all Loading... |
101 helper_->SetBucketData( | 137 helper_->SetBucketData( |
102 bucket_id, offset, part_size, | 138 bucket_id, offset, part_size, |
103 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); | 139 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); |
104 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); | 140 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); |
105 offset += part_size; | 141 offset += part_size; |
106 size -= part_size; | 142 size -= part_size; |
107 } | 143 } |
108 } | 144 } |
109 } | 145 } |
110 | 146 |
111 std::string GLES2Implementation::GetBucketAsString(uint32 bucket_id) { | 147 bool GLES2Implementation::GetBucketAsString( |
| 148 uint32 bucket_id, std::string* str) { |
| 149 DCHECK(str); |
112 std::vector<int8> data; | 150 std::vector<int8> data; |
| 151 // NOTE: strings are passed NULL terminated. That means the empty |
| 152 // string will have a size of 1 and no-string will have a size of 0 |
113 GetBucketContents(bucket_id, &data); | 153 GetBucketContents(bucket_id, &data); |
114 return std::string(reinterpret_cast<char*>(&data[0]), data.size()); | 154 if (data.empty()) { |
| 155 return false; |
| 156 } |
| 157 str->assign(&data[0], &data[0] + data.size() - 1); |
| 158 return true; |
115 } | 159 } |
116 | 160 |
117 void GLES2Implementation::SetBucketAsString( | 161 void GLES2Implementation::SetBucketAsString( |
118 uint32 bucket_id, const std::string& str) { | 162 uint32 bucket_id, const std::string& str) { |
119 SetBucketContents(bucket_id, str.c_str(), str.size()); | 163 // NOTE: strings are passed NULL terminated. That means the empty |
| 164 // string will have a size of 1 and no-string will have a size of 0 |
| 165 SetBucketContents(bucket_id, str.c_str(), str.size() + 1); |
120 } | 166 } |
121 | 167 |
122 void GLES2Implementation::DrawElements( | 168 void GLES2Implementation::DrawElements( |
123 GLenum mode, GLsizei count, GLenum type, const void* indices) { | 169 GLenum mode, GLsizei count, GLenum type, const void* indices) { |
124 helper_->DrawElements(mode, count, type, ToGLuint(indices)); | 170 helper_->DrawElements(mode, count, type, ToGLuint(indices)); |
125 } | 171 } |
126 | 172 |
127 void GLES2Implementation::Flush() { | 173 void GLES2Implementation::Flush() { |
128 // Insert the cmd to call glFlush | 174 // Insert the cmd to call glFlush |
129 helper_->Flush(); | 175 helper_->Flush(); |
(...skipping 20 matching lines...) Expand all Loading... |
150 GLuint index, GLenum pname, void** ptr) { | 196 GLuint index, GLenum pname, void** ptr) { |
151 helper_->GetVertexAttribPointerv( | 197 helper_->GetVertexAttribPointerv( |
152 index, pname, result_shm_id(), result_shm_offset()); | 198 index, pname, result_shm_id(), result_shm_offset()); |
153 WaitForCmd(); | 199 WaitForCmd(); |
154 static_cast<gles2::GetVertexAttribPointerv::Result*>( | 200 static_cast<gles2::GetVertexAttribPointerv::Result*>( |
155 result_buffer_)->CopyResult(ptr); | 201 result_buffer_)->CopyResult(ptr); |
156 }; | 202 }; |
157 | 203 |
158 GLint GLES2Implementation::GetAttribLocation( | 204 GLint GLES2Implementation::GetAttribLocation( |
159 GLuint program, const char* name) { | 205 GLuint program, const char* name) { |
| 206 typedef cmd::GetBucketSize::Result Result; |
| 207 Result* result = GetResultAs<Result*>(); |
| 208 *result = -1; |
160 helper_->GetAttribLocationImmediate( | 209 helper_->GetAttribLocationImmediate( |
161 program, name, result_shm_id(), result_shm_offset()); | 210 program, name, result_shm_id(), result_shm_offset()); |
162 WaitForCmd(); | 211 WaitForCmd(); |
163 return GetResultAs<GLint>(); | 212 return *result; |
164 } | 213 } |
165 | 214 |
166 GLint GLES2Implementation::GetUniformLocation( | 215 GLint GLES2Implementation::GetUniformLocation( |
167 GLuint program, const char* name) { | 216 GLuint program, const char* name) { |
| 217 typedef cmd::GetBucketSize::Result Result; |
| 218 Result* result = GetResultAs<Result*>(); |
| 219 *result = -1; |
168 helper_->GetUniformLocationImmediate( | 220 helper_->GetUniformLocationImmediate( |
169 program, name, result_shm_id(), result_shm_offset()); | 221 program, name, result_shm_id(), result_shm_offset()); |
170 WaitForCmd(); | 222 WaitForCmd(); |
171 return GetResultAs<GLint>(); | 223 return *result; |
172 } | 224 } |
173 | 225 |
174 void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { | 226 void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { |
175 switch (pname) { | 227 switch (pname) { |
176 case GL_PACK_ALIGNMENT: | 228 case GL_PACK_ALIGNMENT: |
177 pack_alignment_ = param; | 229 pack_alignment_ = param; |
178 break; | 230 break; |
179 case GL_UNPACK_ALIGNMENT: | 231 case GL_UNPACK_ALIGNMENT: |
180 unpack_alignment_ = param; | 232 unpack_alignment_ = param; |
181 break; | 233 break; |
182 default: | 234 default: |
183 break; | 235 break; |
184 } | 236 } |
185 helper_->PixelStorei(pname, param); | 237 helper_->PixelStorei(pname, param); |
186 } | 238 } |
187 | 239 |
188 | 240 |
189 void GLES2Implementation::VertexAttribPointer( | 241 void GLES2Implementation::VertexAttribPointer( |
190 GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, | 242 GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, |
191 const void* ptr) { | 243 const void* ptr) { |
192 helper_->VertexAttribPointer(index, size, type, normalized, stride, | 244 helper_->VertexAttribPointer(index, size, type, normalized, stride, |
193 ToGLuint(ptr)); | 245 ToGLuint(ptr)); |
194 } | 246 } |
195 | 247 |
196 void GLES2Implementation::ShaderSource( | 248 void GLES2Implementation::ShaderSource( |
197 GLuint shader, GLsizei count, const char** source, const GLint* length) { | 249 GLuint shader, GLsizei count, const char** source, const GLint* length) { |
| 250 if (count < 0) { |
| 251 SetGLError(GL_INVALID_VALUE); |
| 252 return; |
| 253 } |
198 // TODO(gman): change to use buckets and check that there is enough room. | 254 // TODO(gman): change to use buckets and check that there is enough room. |
199 | 255 |
200 // Compute the total size. | 256 // Compute the total size. |
201 uint32 total_size = 0; | 257 uint32 total_size = 0; |
202 for (GLsizei ii = 0; ii < count; ++ii) { | 258 for (GLsizei ii = 0; ii < count; ++ii) { |
203 total_size += length ? length[ii] : strlen(source[ii]); | 259 total_size += length ? length[ii] : strlen(source[ii]); |
204 } | 260 } |
205 | 261 |
206 // Concatenate all the strings in to the transfer buffer. | 262 // Concatenate all the strings in to the transfer buffer. |
207 char* strings = transfer_buffer_.AllocTyped<char>(total_size); | 263 char* strings = transfer_buffer_.AllocTyped<char>(total_size); |
(...skipping 18 matching lines...) Expand all Loading... |
226 // with the actual data in the case of our transfer buffer being big | 282 // with the actual data in the case of our transfer buffer being big |
227 // enough? | 283 // enough? |
228 helper_->BufferData(target, size, 0, 0, usage); | 284 helper_->BufferData(target, size, 0, 0, usage); |
229 if (data != NULL) { | 285 if (data != NULL) { |
230 BufferSubData(target, 0, size, data); | 286 BufferSubData(target, 0, size, data); |
231 } | 287 } |
232 } | 288 } |
233 | 289 |
234 void GLES2Implementation::BufferSubData( | 290 void GLES2Implementation::BufferSubData( |
235 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { | 291 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { |
| 292 if (size == 0) { |
| 293 return; |
| 294 } |
| 295 |
| 296 if (size < 0) { |
| 297 SetGLError(GL_INVALID_VALUE); |
| 298 return; |
| 299 } |
| 300 |
236 const int8* source = static_cast<const int8*>(data); | 301 const int8* source = static_cast<const int8*>(data); |
237 GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); | 302 GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); |
238 while (size) { | 303 while (size) { |
239 GLsizeiptr part_size = std::min(size, max_size); | 304 GLsizeiptr part_size = std::min(size, max_size); |
240 void* buffer = transfer_buffer_.Alloc(part_size); | 305 void* buffer = transfer_buffer_.Alloc(part_size); |
241 memcpy(buffer, source, part_size); | 306 memcpy(buffer, source, part_size); |
242 helper_->BufferSubData(target, offset, part_size, | 307 helper_->BufferSubData(target, offset, part_size, |
243 transfer_buffer_id_, | 308 transfer_buffer_id_, |
244 transfer_buffer_.GetOffset(buffer)); | 309 transfer_buffer_.GetOffset(buffer)); |
245 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); | 310 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); |
246 offset += part_size; | 311 offset += part_size; |
247 source += part_size; | 312 source += part_size; |
248 size -= part_size; | 313 size -= part_size; |
249 } | 314 } |
250 } | 315 } |
251 | 316 |
252 void GLES2Implementation::CompressedTexImage2D( | 317 void GLES2Implementation::CompressedTexImage2D( |
253 GLenum target, GLint level, GLenum internalformat, GLsizei width, | 318 GLenum target, GLint level, GLenum internalformat, GLsizei width, |
254 GLsizei height, GLint border, GLsizei image_size, const void* data) { | 319 GLsizei height, GLint border, GLsizei image_size, const void* data) { |
255 // TODO(gman): Switch to use buckets alwayst or at least if no room in shared | 320 if (width < 0 || height < 0 || level < 0) { |
| 321 SetGLError(GL_INVALID_VALUE); |
| 322 return; |
| 323 } |
| 324 // TODO(gman): Switch to use buckets always or at least if no room in shared |
256 // memory. | 325 // memory. |
257 DCHECK_LE(image_size, | 326 DCHECK_LE(image_size, |
258 static_cast<GLsizei>( | 327 static_cast<GLsizei>( |
259 transfer_buffer_.GetLargestFreeOrPendingSize())); | 328 transfer_buffer_.GetLargestFreeOrPendingSize())); |
260 void* buffer = transfer_buffer_.Alloc(image_size); | 329 void* buffer = transfer_buffer_.Alloc(image_size); |
261 memcpy(buffer, data, image_size); | 330 memcpy(buffer, data, image_size); |
262 helper_->CompressedTexImage2D( | 331 helper_->CompressedTexImage2D( |
263 target, level, internalformat, width, height, border, image_size, | 332 target, level, internalformat, width, height, border, image_size, |
264 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); | 333 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); |
265 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); | 334 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); |
266 } | 335 } |
267 | 336 |
268 void GLES2Implementation::CompressedTexSubImage2D( | 337 void GLES2Implementation::CompressedTexSubImage2D( |
269 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, | 338 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, |
270 GLsizei height, GLenum format, GLsizei image_size, const void* data) { | 339 GLsizei height, GLenum format, GLsizei image_size, const void* data) { |
271 // TODO(gman): Switch to use buckets alwayst or at least if no room in shared | 340 if (width < 0 || height < 0 || level < 0) { |
| 341 SetGLError(GL_INVALID_VALUE); |
| 342 return; |
| 343 } |
| 344 // TODO(gman): Switch to use buckets always or at least if no room in shared |
272 // memory. | 345 // memory. |
273 DCHECK_LE(image_size, | 346 DCHECK_LE(image_size, |
274 static_cast<GLsizei>( | 347 static_cast<GLsizei>( |
275 transfer_buffer_.GetLargestFreeOrPendingSize())); | 348 transfer_buffer_.GetLargestFreeOrPendingSize())); |
276 void* buffer = transfer_buffer_.Alloc(image_size); | 349 void* buffer = transfer_buffer_.Alloc(image_size); |
277 memcpy(buffer, data, image_size); | 350 memcpy(buffer, data, image_size); |
278 helper_->CompressedTexSubImage2D( | 351 helper_->CompressedTexSubImage2D( |
279 target, level, xoffset, yoffset, width, height, format, image_size, | 352 target, level, xoffset, yoffset, width, height, format, image_size, |
280 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); | 353 transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); |
281 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); | 354 transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); |
282 } | 355 } |
283 | 356 |
284 void GLES2Implementation::TexImage2D( | 357 void GLES2Implementation::TexImage2D( |
285 GLenum target, GLint level, GLint internalformat, GLsizei width, | 358 GLenum target, GLint level, GLint internalformat, GLsizei width, |
286 GLsizei height, GLint border, GLenum format, GLenum type, | 359 GLsizei height, GLint border, GLenum format, GLenum type, |
287 const void* pixels) { | 360 const void* pixels) { |
| 361 if (level < 0 || height < 0 || width < 0) { |
| 362 SetGLError(GL_INVALID_VALUE); |
| 363 return; |
| 364 } |
288 helper_->TexImage2D( | 365 helper_->TexImage2D( |
289 target, level, internalformat, width, height, border, format, type, 0, 0); | 366 target, level, internalformat, width, height, border, format, type, 0, 0); |
290 if (pixels) { | 367 if (pixels) { |
291 TexSubImage2D(target, level, 0, 0, width, height, format, type, pixels); | 368 TexSubImage2D(target, level, 0, 0, width, height, format, type, pixels); |
292 } | 369 } |
293 } | 370 } |
294 | 371 |
295 void GLES2Implementation::TexSubImage2D( | 372 void GLES2Implementation::TexSubImage2D( |
296 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, | 373 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, |
297 GLsizei height, GLenum format, GLenum type, const void* pixels) { | 374 GLsizei height, GLenum format, GLenum type, const void* pixels) { |
| 375 if (level < 0 || height < 0 || width < 0) { |
| 376 SetGLError(GL_INVALID_VALUE); |
| 377 return; |
| 378 } |
298 const int8* source = static_cast<const int8*>(pixels); | 379 const int8* source = static_cast<const int8*>(pixels); |
299 GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); | 380 GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); |
300 GLsizeiptr unpadded_row_size = GLES2Util::ComputeImageDataSize( | 381 GLsizeiptr unpadded_row_size = GLES2Util::ComputeImageDataSize( |
301 width, 1, format, type, unpack_alignment_); | 382 width, 1, format, type, unpack_alignment_); |
302 GLsizeiptr padded_row_size = GLES2Util::ComputeImageDataSize( | 383 GLsizeiptr padded_row_size = GLES2Util::ComputeImageDataSize( |
303 width, 2, format, type, unpack_alignment_) - unpadded_row_size; | 384 width, 2, format, type, unpack_alignment_) - unpadded_row_size; |
304 | 385 |
305 if (padded_row_size <= max_size) { | 386 if (padded_row_size <= max_size) { |
306 // Transfer by rows. | 387 // Transfer by rows. |
307 GLint max_rows = max_size / padded_row_size; | 388 GLint max_rows = max_size / padded_row_size; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 } | 429 } |
349 | 430 |
350 GLenum GLES2Implementation::CheckFramebufferStatus(GLenum target) { | 431 GLenum GLES2Implementation::CheckFramebufferStatus(GLenum target) { |
351 // TODO(gman): implement. | 432 // TODO(gman): implement. |
352 return 0; | 433 return 0; |
353 } | 434 } |
354 | 435 |
355 void GLES2Implementation::GetActiveAttrib( | 436 void GLES2Implementation::GetActiveAttrib( |
356 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, | 437 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, |
357 GLenum* type, char* name) { | 438 GLenum* type, char* name) { |
| 439 if (bufsize < 0) { |
| 440 SetGLError(GL_INVALID_VALUE); |
| 441 return; |
| 442 } |
| 443 // Clear the bucket so if we the command fails nothing will be in it. |
| 444 helper_->SetBucketSize(kResultBucketId, 0); |
358 typedef gles2::GetActiveAttrib::Result Result; | 445 typedef gles2::GetActiveAttrib::Result Result; |
359 Result* result = static_cast<Result*>(result_buffer_); | 446 Result* result = static_cast<Result*>(result_buffer_); |
| 447 // Set as failed so if the command fails we'll recover. |
| 448 result->success = false; |
360 helper_->GetActiveAttrib(program, index, kResultBucketId, | 449 helper_->GetActiveAttrib(program, index, kResultBucketId, |
361 result_shm_id(), result_shm_offset()); | 450 result_shm_id(), result_shm_offset()); |
362 WaitForCmd(); | 451 WaitForCmd(); |
363 if (result->success) { | 452 if (result->success) { |
364 if (size) { | 453 if (size) { |
365 *size = result->size; | 454 *size = result->size; |
366 } | 455 } |
367 if (type) { | 456 if (type) { |
368 *type = result->type; | 457 *type = result->type; |
369 } | 458 } |
370 if (length || name) { | 459 if (length || name) { |
371 std::vector<int8> str; | 460 std::vector<int8> str; |
372 GetBucketContents(kResultBucketId, &str); | 461 GetBucketContents(kResultBucketId, &str); |
373 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1, | 462 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1, |
374 str.size()); | 463 str.size()); |
375 if (length) { | 464 if (length) { |
376 *length = max_size; | 465 *length = max_size; |
377 } | 466 } |
378 if (name && bufsize > 0) { | 467 if (name && bufsize > 0) { |
379 memcpy(name, &str[0], max_size); | 468 memcpy(name, &str[0], max_size); |
380 name[max_size] = '\0'; | 469 name[max_size] = '\0'; |
381 } | 470 } |
382 } | 471 } |
383 } | 472 } |
384 } | 473 } |
385 | 474 |
386 void GLES2Implementation::GetActiveUniform( | 475 void GLES2Implementation::GetActiveUniform( |
387 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, | 476 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, |
388 GLenum* type, char* name) { | 477 GLenum* type, char* name) { |
| 478 if (bufsize < 0) { |
| 479 SetGLError(GL_INVALID_VALUE); |
| 480 return; |
| 481 } |
| 482 // Clear the bucket so if we the command fails nothing will be in it. |
| 483 helper_->SetBucketSize(kResultBucketId, 0); |
389 typedef gles2::GetActiveUniform::Result Result; | 484 typedef gles2::GetActiveUniform::Result Result; |
390 Result* result = static_cast<Result*>(result_buffer_); | 485 Result* result = static_cast<Result*>(result_buffer_); |
| 486 // Set as failed so if the command fails we'll recover. |
| 487 result->success = false; |
391 helper_->GetActiveUniform(program, index, kResultBucketId, | 488 helper_->GetActiveUniform(program, index, kResultBucketId, |
392 result_shm_id(), result_shm_offset()); | 489 result_shm_id(), result_shm_offset()); |
393 WaitForCmd(); | 490 WaitForCmd(); |
394 if (result->success) { | 491 if (result->success) { |
395 if (size) { | 492 if (size) { |
396 *size = result->size; | 493 *size = result->size; |
397 } | 494 } |
398 if (type) { | 495 if (type) { |
399 *type = result->type; | 496 *type = result->type; |
400 } | 497 } |
401 if (length || name) { | 498 if (length || name) { |
402 std::vector<int8> str; | 499 std::vector<int8> str; |
403 GetBucketContents(kResultBucketId, &str); | 500 GetBucketContents(kResultBucketId, &str); |
404 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1, | 501 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1, |
405 str.size()); | 502 str.size()); |
406 if (length) { | 503 if (length) { |
407 *length = max_size; | 504 *length = max_size; |
408 } | 505 } |
409 if (name && bufsize > 0) { | 506 if (name && bufsize > 0) { |
410 memcpy(name, &str[0], max_size); | 507 memcpy(name, &str[0], max_size); |
411 name[max_size] = '\0'; | 508 name[max_size] = '\0'; |
412 } | 509 } |
413 } | 510 } |
414 } | 511 } |
415 } | 512 } |
416 | 513 |
417 void GLES2Implementation::GetAttachedShaders( | 514 void GLES2Implementation::GetAttachedShaders( |
418 GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { | 515 GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { |
| 516 if (maxcount < 0) { |
| 517 SetGLError(GL_INVALID_VALUE); |
| 518 return; |
| 519 } |
419 typedef gles2::GetAttachedShaders::Result Result; | 520 typedef gles2::GetAttachedShaders::Result Result; |
420 uint32 size = Result::ComputeSize(maxcount); | 521 uint32 size = Result::ComputeSize(maxcount); |
421 Result* result = transfer_buffer_.AllocTyped<Result>(size); | 522 Result* result = transfer_buffer_.AllocTyped<Result>(size); |
422 helper_->GetAttachedShaders( | 523 helper_->GetAttachedShaders( |
423 program, | 524 program, |
424 transfer_buffer_id_, | 525 transfer_buffer_id_, |
425 transfer_buffer_.GetOffset(result), | 526 transfer_buffer_.GetOffset(result), |
426 size); | 527 size); |
427 int32 token = helper_->InsertToken(); | 528 int32 token = helper_->InsertToken(); |
428 WaitForCmd(); | 529 WaitForCmd(); |
429 if (count) { | 530 if (count) { |
430 *count = result->GetNumResults(); | 531 *count = result->GetNumResults(); |
431 } | 532 } |
432 result->CopyResult(shaders); | 533 result->CopyResult(shaders); |
433 transfer_buffer_.FreePendingToken(result, token); | 534 transfer_buffer_.FreePendingToken(result, token); |
434 } | 535 } |
435 | 536 |
436 void GLES2Implementation::GetProgramInfoLog( | |
437 GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) { | |
438 // TODO(gman): implement. | |
439 } | |
440 | |
441 void GLES2Implementation::GetShaderInfoLog( | |
442 GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) { | |
443 // TODO(gman): implement. | |
444 } | |
445 | |
446 void GLES2Implementation::GetShaderPrecisionFormat( | 537 void GLES2Implementation::GetShaderPrecisionFormat( |
447 GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { | 538 GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { |
448 typedef gles2::GetShaderPrecisionFormat::Result Result; | 539 typedef gles2::GetShaderPrecisionFormat::Result Result; |
449 Result* result = static_cast<Result*>(result_buffer_); | 540 Result* result = static_cast<Result*>(result_buffer_); |
450 helper_->GetShaderPrecisionFormat( | 541 helper_->GetShaderPrecisionFormat( |
451 shadertype, precisiontype, result_shm_id(), result_shm_offset()); | 542 shadertype, precisiontype, result_shm_id(), result_shm_offset()); |
452 WaitForCmd(); | 543 WaitForCmd(); |
453 if (result->success) { | 544 if (result->success) { |
454 if (range) { | 545 if (range) { |
455 range[0] = result->min_range; | 546 range[0] = result->min_range; |
456 range[1] = result->max_range; | 547 range[1] = result->max_range; |
457 } | 548 } |
458 if (precision) { | 549 if (precision) { |
459 precision[0] = result->precision; | 550 precision[0] = result->precision; |
460 } | 551 } |
461 } | 552 } |
462 } | 553 } |
463 | 554 |
464 void GLES2Implementation::GetShaderSource( | |
465 GLuint shader, GLsizei bufsize, GLsizei* length, char* source) { | |
466 // TODO(gman): implement. | |
467 } | |
468 | |
469 const GLubyte* GLES2Implementation::GetString(GLenum name) { | 555 const GLubyte* GLES2Implementation::GetString(GLenum name) { |
470 // TODO(gman): implement. | 556 const char* result; |
471 return 0; | 557 GLStringMap::const_iterator it = gl_strings_.find(name); |
| 558 if (it != gl_strings_.end()) { |
| 559 result = it->second.c_str(); |
| 560 } else { |
| 561 // Clear the bucket so if we the command fails nothing will be in it. |
| 562 helper_->SetBucketSize(kResultBucketId, 0); |
| 563 helper_->GetString(name, kResultBucketId); |
| 564 std::string str; |
| 565 if (GetBucketAsString(kResultBucketId, &str)) { |
| 566 std::pair<GLStringMap::const_iterator, bool> insert_result = |
| 567 gl_strings_.insert(std::make_pair(name, str)); |
| 568 DCHECK(insert_result.second); |
| 569 result = insert_result.first->second.c_str(); |
| 570 } else { |
| 571 result = NULL; |
| 572 } |
| 573 } |
| 574 return reinterpret_cast<const GLubyte*>(result); |
472 } | 575 } |
473 | 576 |
474 void GLES2Implementation::GetUniformfv( | 577 void GLES2Implementation::GetUniformfv( |
475 GLuint program, GLint location, GLfloat* params) { | 578 GLuint program, GLint location, GLfloat* params) { |
476 helper_->GetUniformfv( | 579 helper_->GetUniformfv( |
477 program, location, result_shm_id(), result_shm_offset()); | 580 program, location, result_shm_id(), result_shm_offset()); |
478 WaitForCmd(); | 581 WaitForCmd(); |
479 static_cast<gles2::GetUniformfv::Result*>(result_buffer_)->CopyResult(params); | 582 static_cast<gles2::GetUniformfv::Result*>(result_buffer_)->CopyResult(params); |
480 } | 583 } |
481 | 584 |
482 void GLES2Implementation::GetUniformiv( | 585 void GLES2Implementation::GetUniformiv( |
483 GLuint program, GLint location, GLint* params) { | 586 GLuint program, GLint location, GLint* params) { |
484 helper_->GetUniformiv( | 587 helper_->GetUniformiv( |
485 program, location, result_shm_id(), result_shm_offset()); | 588 program, location, result_shm_id(), result_shm_offset()); |
486 WaitForCmd(); | 589 WaitForCmd(); |
487 static_cast<gles2::GetUniformfv::Result*>(result_buffer_)->CopyResult(params); | 590 static_cast<gles2::GetUniformfv::Result*>(result_buffer_)->CopyResult(params); |
488 } | 591 } |
489 | 592 |
490 void GLES2Implementation::ReadPixels( | 593 void GLES2Implementation::ReadPixels( |
491 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, | 594 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, |
492 GLenum type, void* pixels) { | 595 GLenum type, void* pixels) { |
493 // Note: Negative widths and heights are not handled here but are handled | 596 // Note: Negative widths and heights are not handled here but are handled |
494 // by the service side so the glGetError wrapping works. | 597 // by the service side so the glGetError wrapping works. |
| 598 if (width < 0 || height < 0) { |
| 599 SetGLError(GL_INVALID_VALUE); |
| 600 return; |
| 601 } |
495 if (width == 0 || height == 0) { | 602 if (width == 0 || height == 0) { |
496 return; | 603 return; |
497 } | 604 } |
498 typedef gles2::ReadPixels::Result Result; | 605 typedef gles2::ReadPixels::Result Result; |
499 Result* result = static_cast<Result*>(result_buffer_); | 606 Result* result = static_cast<Result*>(result_buffer_); |
500 int8* dest = reinterpret_cast<int8*>(pixels); | 607 int8* dest = reinterpret_cast<int8*>(pixels); |
501 GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); | 608 GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); |
502 GLsizeiptr unpadded_row_size = GLES2Util::ComputeImageDataSize( | 609 GLsizeiptr unpadded_row_size = GLES2Util::ComputeImageDataSize( |
503 width, 1, format, type, pack_alignment_); | 610 width, 1, format, type, pack_alignment_); |
504 GLsizeiptr padded_row_size = GLES2Util::ComputeImageDataSize( | 611 GLsizeiptr padded_row_size = GLES2Util::ComputeImageDataSize( |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 temp_width -= num_pixels; | 664 temp_width -= num_pixels; |
558 } | 665 } |
559 ++yoffset; | 666 ++yoffset; |
560 dest += padded_row_size; | 667 dest += padded_row_size; |
561 } | 668 } |
562 } | 669 } |
563 } | 670 } |
564 | 671 |
565 } // namespace gles2 | 672 } // namespace gles2 |
566 } // namespace gpu | 673 } // namespace gpu |
OLD | NEW |