Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(682)

Side by Side Diff: cc/texture_uploader.cc

Issue 11229040: Fix glTexSubImage2D for non-32bpp formats. (Closed) Base URL: https://git.chromium.org/git/chromium/src@git-svn
Patch Set: Rebase.:wq Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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 #include "config.h" 5 #include "config.h"
6 6
7 #include "cc/texture_uploader.h" 7 #include "cc/texture_uploader.h"
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/debug/alias.h" 12 #include "base/debug/alias.h"
13 #include "base/debug/trace_event.h" 13 #include "base/debug/trace_event.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "cc/prioritized_texture.h" 15 #include "cc/prioritized_texture.h"
16 #include "third_party/khronos/GLES2/gl2.h" 16 #include "third_party/khronos/GLES2/gl2.h"
17 #include "third_party/khronos/GLES2/gl2ext.h" 17 #include "third_party/khronos/GLES2/gl2ext.h"
18 #include <public/WebGraphicsContext3D.h> 18 #include <public/WebGraphicsContext3D.h>
19 19
20 namespace { 20 namespace {
21 21
22 // How many previous uploads to use when predicting future throughput. 22 // How many previous uploads to use when predicting future throughput.
23 static const size_t uploadHistorySize = 100; 23 static const size_t uploadHistorySize = 100;
24 24
25 // Global estimated number of textures per second to maintain estimates across 25 // Global estimated number of textures per second to maintain estimates across
26 // subsequent instances of TextureUploader. 26 // subsequent instances of TextureUploader.
27 // More than one thread will not access this variable, so we do not need to sync hronize access. 27 // More than one thread will not access this variable, so we do not need to
28 // synchronize access.
enne (OOO) 2012/10/22 20:36:14 Please do not update style along with behavior cha
sheu 2012/10/22 21:31:59 I thought this would be small enough to slip in.
28 static double estimatedTexturesPerSecondGlobal = 48.0 * 60.0; 29 static double estimatedTexturesPerSecondGlobal = 48.0 * 60.0;
29 30
30 } // anonymous namespace 31 } // anonymous namespace
31 32
32 namespace cc { 33 namespace cc {
33 34
34 TextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) 35 TextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context)
35 : m_context(context) 36 : m_context(context)
36 , m_queryId(0) 37 , m_queryId(0)
37 , m_value(0) 38 , m_value(0)
(...skipping 16 matching lines...) Expand all
54 } 55 }
55 56
56 void TextureUploader::Query::end() 57 void TextureUploader::Query::end()
57 { 58 {
58 m_context->endQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); 59 m_context->endQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
59 } 60 }
60 61
61 bool TextureUploader::Query::isPending() 62 bool TextureUploader::Query::isPending()
62 { 63 {
63 unsigned available = 1; 64 unsigned available = 1;
64 m_context->getQueryObjectuivEXT(m_queryId, GL_QUERY_RESULT_AVAILABLE_EXT, &a vailable); 65 m_context->getQueryObjectuivEXT(m_queryId, GL_QUERY_RESULT_AVAILABLE_EXT,
66 &available);
65 return !available; 67 return !available;
66 } 68 }
67 69
68 unsigned TextureUploader::Query::value() 70 unsigned TextureUploader::Query::value()
69 { 71 {
70 if (!m_hasValue) { 72 if (!m_hasValue) {
71 m_context->getQueryObjectuivEXT(m_queryId, GL_QUERY_RESULT_EXT, &m_value ); 73 m_context->getQueryObjectuivEXT(m_queryId, GL_QUERY_RESULT_EXT,
74 &m_value);
72 m_hasValue = true; 75 m_hasValue = true;
73 } 76 }
74 return m_value; 77 return m_value;
75 } 78 }
76 79
77 void TextureUploader::Query::markAsNonBlocking() 80 void TextureUploader::Query::markAsNonBlocking()
78 { 81 {
79 m_isNonBlocking = true; 82 m_isNonBlocking = true;
80 } 83 }
81 84
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 (*it)->markAsNonBlocking(); 119 (*it)->markAsNonBlocking();
117 } 120 }
118 121
119 DCHECK(!m_numBlockingTextureUploads); 122 DCHECK(!m_numBlockingTextureUploads);
120 } 123 }
121 124
122 double TextureUploader::estimatedTexturesPerSecond() 125 double TextureUploader::estimatedTexturesPerSecond()
123 { 126 {
124 processQueries(); 127 processQueries();
125 128
126 // The history should never be empty because we initialize all elements with an estimate. 129 // The history should never be empty because we initialize all elements with
130 // an estimate.
127 DCHECK(m_texturesPerSecondHistory.size() == uploadHistorySize); 131 DCHECK(m_texturesPerSecondHistory.size() == uploadHistorySize);
128 132
129 // Sort the history and use the median as our estimate. 133 // Sort the history and use the median as our estimate.
130 std::vector<double> sortedHistory(m_texturesPerSecondHistory.begin(), 134 std::vector<double> sortedHistory(m_texturesPerSecondHistory.begin(),
131 m_texturesPerSecondHistory.end()); 135 m_texturesPerSecondHistory.end());
132 std::sort(sortedHistory.begin(), sortedHistory.end()); 136 std::sort(sortedHistory.begin(), sortedHistory.end());
133 137
134 estimatedTexturesPerSecondGlobal = sortedHistory[sortedHistory.size() * 2 / 3]; 138 estimatedTexturesPerSecondGlobal =
135 TRACE_COUNTER1("cc", "estimatedTexturesPerSecond", estimatedTexturesPerSecon dGlobal); 139 sortedHistory[sortedHistory.size() * 2 / 3];
140 TRACE_COUNTER1("cc", "estimatedTexturesPerSecond",
141 estimatedTexturesPerSecondGlobal);
136 return estimatedTexturesPerSecondGlobal; 142 return estimatedTexturesPerSecondGlobal;
137 } 143 }
138 144
139 void TextureUploader::beginQuery() 145 void TextureUploader::beginQuery()
140 { 146 {
141 if (m_availableQueries.isEmpty()) 147 if (m_availableQueries.isEmpty())
142 m_availableQueries.append(Query::create(m_context)); 148 m_availableQueries.append(Query::create(m_context));
143 149
144 m_availableQueries.first()->begin(); 150 m_availableQueries.first()->begin();
145 } 151 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 base::debug::Alias(&image_rect_height); 211 base::debug::Alias(&image_rect_height);
206 base::debug::Alias(&dest_offset_width); 212 base::debug::Alias(&dest_offset_width);
207 base::debug::Alias(&dest_offset_height); 213 base::debug::Alias(&dest_offset_height);
208 TRACE_EVENT0("cc", "TextureUploader::uploadWithTexSubImage"); 214 TRACE_EVENT0("cc", "TextureUploader::uploadWithTexSubImage");
209 215
210 // Offset from image-rect to source-rect. 216 // Offset from image-rect to source-rect.
211 IntPoint offset(source_rect.x() - image_rect.x(), 217 IntPoint offset(source_rect.x() - image_rect.x(),
212 source_rect.y() - image_rect.y()); 218 source_rect.y() - image_rect.y());
213 219
214 const uint8_t* pixel_source; 220 const uint8_t* pixel_source;
221
222 unsigned int components_per_pixel = 0;
223 unsigned int bytes_per_component = 1;
224 switch (format) {
enne (OOO) 2012/10/22 20:36:14 Can you not duplicate this switch statement from b
sheu 2012/10/22 21:31:59 Done.
225 case GL_RGBA:
226 case GL_BGRA_EXT:
227 components_per_pixel = 4;
228 break;
229 case GL_LUMINANCE:
230 components_per_pixel = 1;
231 break;
232 default:
233 NOTREACHED();
234 }
235 unsigned int bytes_per_pixel = components_per_pixel * bytes_per_component;
236
215 if (image_rect.width() == source_rect.width() && !offset.x()) { 237 if (image_rect.width() == source_rect.width() && !offset.x()) {
216 pixel_source = &image[4 * offset.y() * image_rect.width()]; 238 pixel_source = &image[bytes_per_pixel * offset.y() * image_rect.width()] ;
217 } else { 239 } else {
218 size_t needed_size = source_rect.width() * source_rect.height() * 4; 240 size_t needed_size =
241 source_rect.width() * source_rect.height() * bytes_per_pixel;
219 if (m_subImageSize < needed_size) { 242 if (m_subImageSize < needed_size) {
220 m_subImage.reset(new uint8_t[needed_size]); 243 m_subImage.reset(new uint8_t[needed_size]);
221 m_subImageSize = needed_size; 244 m_subImageSize = needed_size;
222 } 245 }
223 // Strides not equal, so do a row-by-row memcpy from the 246 // Strides not equal, so do a row-by-row memcpy from the
224 // paint results into a temp buffer for uploading. 247 // paint results into a temp buffer for uploading.
225 for (int row = 0; row < source_rect.height(); ++row) 248 for (int row = 0; row < source_rect.height(); ++row)
226 memcpy(&m_subImage[source_rect.width() * 4 * row], 249 memcpy(&m_subImage[source_rect.width() * bytes_per_pixel * row],
227 &image[4 * (offset.x() + 250 &image[bytes_per_pixel * (offset.x() +
228 (offset.y() + row) * image_rect.width())], 251 (offset.y() + row) * image_rect.width())],
229 source_rect.width() * 4); 252 source_rect.width() * bytes_per_pixel);
230 253
231 pixel_source = &m_subImage[0]; 254 pixel_source = &m_subImage[0];
232 } 255 }
233 256
234 m_context->texSubImage2D(GL_TEXTURE_2D, 257 m_context->texSubImage2D(GL_TEXTURE_2D,
235 0, 258 0,
236 dest_offset.width(), 259 dest_offset.width(),
237 dest_offset.height(), 260 dest_offset.height(),
238 source_rect.width(), 261 source_rect.width(),
239 source_rect.height(), 262 source_rect.height(),
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 GL_UNSIGNED_BYTE, 312 GL_UNSIGNED_BYTE,
290 GL_WRITE_ONLY)); 313 GL_WRITE_ONLY));
291 314
292 if (!pixel_dest) { 315 if (!pixel_dest) {
293 uploadWithTexSubImage( 316 uploadWithTexSubImage(
294 image, image_rect, source_rect, dest_offset, format); 317 image, image_rect, source_rect, dest_offset, format);
295 return; 318 return;
296 } 319 }
297 320
298 unsigned int components_per_pixel = 0; 321 unsigned int components_per_pixel = 0;
322 unsigned int bytes_per_component = 1;
299 switch (format) { 323 switch (format) {
300 case GL_RGBA: 324 case GL_RGBA:
301 case GL_BGRA_EXT: 325 case GL_BGRA_EXT:
302 components_per_pixel = 4; 326 components_per_pixel = 4;
303 break; 327 break;
304 case GL_LUMINANCE: 328 case GL_LUMINANCE:
305 components_per_pixel = 1; 329 components_per_pixel = 1;
306 break; 330 break;
307 default: 331 default:
308 NOTREACHED(); 332 NOTREACHED();
309 } 333 }
310 unsigned int bytes_per_component = 1;
311 unsigned int bytes_per_pixel = components_per_pixel * bytes_per_component; 334 unsigned int bytes_per_pixel = components_per_pixel * bytes_per_component;
312 335
313 if (image_rect.width() == source_rect.width() && !offset.x()) { 336 if (image_rect.width() == source_rect.width() && !offset.x()) {
314 memcpy(pixel_dest, 337 memcpy(pixel_dest,
315 &image[offset.y() * image_rect.width() * bytes_per_pixel], 338 &image[offset.y() * image_rect.width() * bytes_per_pixel],
316 image_rect.width() * source_rect.height() * bytes_per_pixel); 339 image_rect.width() * source_rect.height() * bytes_per_pixel);
317 } else { 340 } else {
318 // Strides not equal, so do a row-by-row memcpy from the 341 // Strides not equal, so do a row-by-row memcpy from the
319 // paint results into the pixelDest 342 // paint results into the pixelDest
320 for (int row = 0; row < source_rect.height(); ++row) 343 for (int row = 0; row < source_rect.height(); ++row)
321 memcpy(&pixel_dest[source_rect.width() * row * bytes_per_pixel], 344 memcpy(&pixel_dest[source_rect.width() * row * bytes_per_pixel],
322 &image[4 * (offset.x() + 345 &image[bytes_per_pixel * (offset.x() +
323 (offset.y() + row) * image_rect.width())], 346 (offset.y() + row) * image_rect.width())],
324 source_rect.width() * bytes_per_pixel); 347 source_rect.width() * bytes_per_pixel);
325 } 348 }
326 349
327 m_context->unmapTexSubImage2DCHROMIUM(pixel_dest); 350 m_context->unmapTexSubImage2DCHROMIUM(pixel_dest);
328 } 351 }
329 352
330 void TextureUploader::processQueries() 353 void TextureUploader::processQueries()
331 { 354 {
332 while (!m_pendingQueries.isEmpty()) { 355 while (!m_pendingQueries.isEmpty()) {
333 if (m_pendingQueries.first()->isPending()) 356 if (m_pendingQueries.first()->isPending())
334 break; 357 break;
335 358
336 unsigned usElapsed = m_pendingQueries.first()->value(); 359 unsigned usElapsed = m_pendingQueries.first()->value();
337 HISTOGRAM_CUSTOM_COUNTS("Renderer4.TextureGpuUploadTimeUS", usElapsed, 0 , 100000, 50); 360 HISTOGRAM_CUSTOM_COUNTS("Renderer4.TextureGpuUploadTimeUS", usElapsed,
361 0, 100000, 50);
338 362
339 if (!m_pendingQueries.first()->isNonBlocking()) 363 if (!m_pendingQueries.first()->isNonBlocking())
340 m_numBlockingTextureUploads--; 364 m_numBlockingTextureUploads--;
341 365
342 // Remove the oldest values from our history and insert the new one 366 // Remove the oldest values from our history and insert the new one
343 double texturesPerSecond = 1.0 / (usElapsed * 1e-6); 367 double texturesPerSecond = 1.0 / (usElapsed * 1e-6);
344 m_texturesPerSecondHistory.pop_back(); 368 m_texturesPerSecondHistory.pop_back();
345 m_texturesPerSecondHistory.push_front(texturesPerSecond); 369 m_texturesPerSecondHistory.push_front(texturesPerSecond);
346 370
347 m_availableQueries.append(m_pendingQueries.takeFirst()); 371 m_availableQueries.append(m_pendingQueries.takeFirst());
348 } 372 }
349 } 373 }
350 374
351 } 375 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698