OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/gl/gl_image_memory.h" | 5 #include "ui/gl/gl_image_memory.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/trace_event/trace_event.h" | 8 #include "base/trace_event/trace_event.h" |
9 #include "ui/gfx/buffer_format_util.h" | |
9 #include "ui/gl/gl_bindings.h" | 10 #include "ui/gl/gl_bindings.h" |
10 | 11 |
11 namespace gfx { | 12 namespace gfx { |
12 namespace { | 13 namespace { |
13 | 14 |
14 bool ValidInternalFormat(unsigned internalformat) { | 15 bool ValidInternalFormat(unsigned internalformat) { |
15 switch (internalformat) { | 16 switch (internalformat) { |
16 case GL_ATC_RGB_AMD: | 17 case GL_ATC_RGB_AMD: |
17 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: | 18 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: |
18 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | 19 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: |
19 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | 20 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: |
20 case GL_ETC1_RGB8_OES: | 21 case GL_ETC1_RGB8_OES: |
21 case GL_R8: | 22 case GL_R8: |
23 case GL_RGB: | |
22 case GL_RGBA: | 24 case GL_RGBA: |
23 case GL_BGRA_EXT: | 25 case GL_BGRA_EXT: |
24 return true; | 26 return true; |
25 default: | 27 default: |
26 return false; | 28 return false; |
27 } | 29 } |
28 } | 30 } |
29 | 31 |
30 bool ValidFormat(BufferFormat format) { | 32 bool ValidFormat(BufferFormat format) { |
31 switch (format) { | 33 switch (format) { |
32 case BufferFormat::ATC: | 34 case BufferFormat::ATC: |
33 case BufferFormat::ATCIA: | 35 case BufferFormat::ATCIA: |
34 case BufferFormat::DXT1: | 36 case BufferFormat::DXT1: |
35 case BufferFormat::DXT5: | 37 case BufferFormat::DXT5: |
36 case BufferFormat::ETC1: | 38 case BufferFormat::ETC1: |
37 case BufferFormat::R_8: | 39 case BufferFormat::R_8: |
38 case BufferFormat::RGBA_4444: | 40 case BufferFormat::RGBA_4444: |
41 case BufferFormat::RGBX_8888: | |
39 case BufferFormat::RGBA_8888: | 42 case BufferFormat::RGBA_8888: |
43 case BufferFormat::BGRX_8888: | |
40 case BufferFormat::BGRA_8888: | 44 case BufferFormat::BGRA_8888: |
41 return true; | 45 return true; |
42 case BufferFormat::BGRX_8888: | |
43 case BufferFormat::YUV_420: | 46 case BufferFormat::YUV_420: |
44 case BufferFormat::YUV_420_BIPLANAR: | 47 case BufferFormat::YUV_420_BIPLANAR: |
45 case BufferFormat::UYVY_422: | 48 case BufferFormat::UYVY_422: |
46 return false; | 49 return false; |
47 } | 50 } |
48 | 51 |
49 NOTREACHED(); | 52 NOTREACHED(); |
50 return false; | 53 return false; |
51 } | 54 } |
52 | 55 |
53 bool IsCompressedFormat(BufferFormat format) { | 56 bool IsCompressedFormat(BufferFormat format) { |
54 switch (format) { | 57 switch (format) { |
55 case BufferFormat::ATC: | 58 case BufferFormat::ATC: |
56 case BufferFormat::ATCIA: | 59 case BufferFormat::ATCIA: |
57 case BufferFormat::DXT1: | 60 case BufferFormat::DXT1: |
58 case BufferFormat::DXT5: | 61 case BufferFormat::DXT5: |
59 case BufferFormat::ETC1: | 62 case BufferFormat::ETC1: |
60 return true; | 63 return true; |
61 case BufferFormat::R_8: | 64 case BufferFormat::R_8: |
62 case BufferFormat::RGBA_4444: | 65 case BufferFormat::RGBA_4444: |
66 case BufferFormat::RGBX_8888: | |
63 case BufferFormat::RGBA_8888: | 67 case BufferFormat::RGBA_8888: |
68 case BufferFormat::BGRX_8888: | |
64 case BufferFormat::BGRA_8888: | 69 case BufferFormat::BGRA_8888: |
65 case BufferFormat::BGRX_8888: | |
66 case BufferFormat::YUV_420: | 70 case BufferFormat::YUV_420: |
67 case BufferFormat::YUV_420_BIPLANAR: | 71 case BufferFormat::YUV_420_BIPLANAR: |
68 case BufferFormat::UYVY_422: | 72 case BufferFormat::UYVY_422: |
69 return false; | 73 return false; |
70 } | 74 } |
71 | 75 |
72 NOTREACHED(); | 76 NOTREACHED(); |
73 return false; | 77 return false; |
74 } | 78 } |
75 | 79 |
76 GLenum TextureFormat(BufferFormat format) { | 80 GLenum TextureFormat(BufferFormat format) { |
77 switch (format) { | 81 switch (format) { |
78 case BufferFormat::ATC: | 82 case BufferFormat::ATC: |
79 return GL_ATC_RGB_AMD; | 83 return GL_ATC_RGB_AMD; |
80 case BufferFormat::ATCIA: | 84 case BufferFormat::ATCIA: |
81 return GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD; | 85 return GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD; |
82 case BufferFormat::DXT1: | 86 case BufferFormat::DXT1: |
83 return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; | 87 return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; |
84 case BufferFormat::DXT5: | 88 case BufferFormat::DXT5: |
85 return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; | 89 return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; |
86 case BufferFormat::ETC1: | 90 case BufferFormat::ETC1: |
87 return GL_ETC1_RGB8_OES; | 91 return GL_ETC1_RGB8_OES; |
88 case BufferFormat::R_8: | 92 case BufferFormat::R_8: |
89 return GL_RED; | 93 return GL_RED; |
90 case BufferFormat::RGBA_4444: | 94 case BufferFormat::RGBA_4444: |
91 case BufferFormat::RGBA_8888: | 95 case BufferFormat::RGBA_8888: |
92 return GL_RGBA; | 96 return GL_RGBA; |
93 case BufferFormat::BGRA_8888: | 97 case BufferFormat::BGRA_8888: |
94 return GL_BGRA_EXT; | 98 return GL_BGRA_EXT; |
99 case BufferFormat::RGBX_8888: | |
95 case BufferFormat::BGRX_8888: | 100 case BufferFormat::BGRX_8888: |
101 return GL_RGB; | |
96 case BufferFormat::YUV_420: | 102 case BufferFormat::YUV_420: |
97 case BufferFormat::YUV_420_BIPLANAR: | 103 case BufferFormat::YUV_420_BIPLANAR: |
98 case BufferFormat::UYVY_422: | 104 case BufferFormat::UYVY_422: |
99 NOTREACHED(); | 105 NOTREACHED(); |
100 return 0; | 106 return 0; |
101 } | 107 } |
102 | 108 |
103 NOTREACHED(); | 109 NOTREACHED(); |
104 return 0; | 110 return 0; |
105 } | 111 } |
106 | 112 |
107 GLenum DataFormat(BufferFormat format) { | 113 GLenum DataFormat(BufferFormat format) { |
108 return TextureFormat(format); | 114 switch (format) { |
115 case BufferFormat::RGBX_8888: | |
116 return GL_RGBA; | |
117 case BufferFormat::BGRX_8888: | |
118 return GL_BGRA_EXT; | |
119 case BufferFormat::RGBA_4444: | |
120 case BufferFormat::RGBA_8888: | |
121 case BufferFormat::BGRA_8888: | |
122 case BufferFormat::R_8: | |
123 case BufferFormat::ATC: | |
124 case BufferFormat::ATCIA: | |
125 case BufferFormat::DXT1: | |
126 case BufferFormat::DXT5: | |
127 case BufferFormat::ETC1: | |
128 case BufferFormat::YUV_420: | |
129 case BufferFormat::YUV_420_BIPLANAR: | |
130 case BufferFormat::UYVY_422: | |
131 return TextureFormat(format); | |
132 } | |
133 | |
134 NOTREACHED(); | |
135 return 0; | |
109 } | 136 } |
110 | 137 |
111 GLenum DataType(BufferFormat format) { | 138 GLenum DataType(BufferFormat format) { |
112 switch (format) { | 139 switch (format) { |
113 case BufferFormat::RGBA_4444: | 140 case BufferFormat::RGBA_4444: |
114 return GL_UNSIGNED_SHORT_4_4_4_4; | 141 return GL_UNSIGNED_SHORT_4_4_4_4; |
115 case BufferFormat::RGBA_8888: | 142 case BufferFormat::RGBA_8888: |
116 case BufferFormat::BGRA_8888: | 143 case BufferFormat::BGRA_8888: |
117 case BufferFormat::R_8: | 144 case BufferFormat::R_8: |
118 return GL_UNSIGNED_BYTE; | 145 return GL_UNSIGNED_BYTE; |
146 case BufferFormat::RGBX_8888: | |
147 return GL_UNSIGNED_INT_8_8_8_8; | |
148 case BufferFormat::BGRX_8888: | |
149 return GL_UNSIGNED_INT_8_8_8_8_REV; | |
piman
2015/10/23 00:52:44
Hmm, I'm not sure what the expectation is here. Th
reveman
2015/10/23 13:44:43
Yea, that made no sense. Thanks for noticing. Late
| |
119 case BufferFormat::ATC: | 150 case BufferFormat::ATC: |
120 case BufferFormat::ATCIA: | 151 case BufferFormat::ATCIA: |
121 case BufferFormat::DXT1: | 152 case BufferFormat::DXT1: |
122 case BufferFormat::DXT5: | 153 case BufferFormat::DXT5: |
123 case BufferFormat::ETC1: | 154 case BufferFormat::ETC1: |
124 case BufferFormat::BGRX_8888: | |
125 case BufferFormat::YUV_420: | 155 case BufferFormat::YUV_420: |
126 case BufferFormat::YUV_420_BIPLANAR: | 156 case BufferFormat::YUV_420_BIPLANAR: |
127 case BufferFormat::UYVY_422: | 157 case BufferFormat::UYVY_422: |
128 NOTREACHED(); | 158 NOTREACHED(); |
129 return 0; | 159 return 0; |
130 } | 160 } |
131 | 161 |
132 NOTREACHED(); | 162 NOTREACHED(); |
133 return 0; | 163 return 0; |
134 } | 164 } |
135 | 165 |
136 GLsizei SizeInBytes(const Size& size, BufferFormat format) { | 166 template <typename F> |
137 size_t stride_in_bytes = 0; | 167 scoped_ptr<uint8_t[]> GLES2RGBData(const Size& size, |
138 bool valid_stride = GLImageMemory::StrideInBytes( | 168 BufferFormat format, |
139 size.width(), format, &stride_in_bytes); | 169 const uint8_t* data, |
140 DCHECK(valid_stride); | 170 F const& data_to_rgb, |
141 return static_cast<GLsizei>(stride_in_bytes * size.height()); | 171 GLenum* data_format, |
172 GLenum* data_type) { | |
173 TRACE_EVENT2("gpu", "GLES2RGBData", "width", size.width(), "height", | |
174 size.height()); | |
175 | |
176 // Four-byte row alignment as specified by glPixelStorei with argument | |
177 // GL_UNPACK_ALIGNMENT set to 4. | |
178 size_t gles2_rgb_data_stride = (size.width() * 3 + 3) & ~3; | |
179 scoped_ptr<uint8_t[]> gles2_rgb_data( | |
180 new uint8_t[gles2_rgb_data_stride * size.height()]); | |
181 size_t data_stride = RowSizeForBufferFormat(size.width(), format, 0); | |
182 | |
183 for (int y = 0; y < size.height(); ++y) { | |
184 for (int x = 0; x < size.width(); ++x) { | |
185 data_to_rgb(&data[y * data_stride + x * 4], | |
186 &gles2_rgb_data[y * gles2_rgb_data_stride + x * 3]); | |
187 } | |
188 } | |
189 | |
190 *data_format = GL_RGB; | |
191 *data_type = GL_UNSIGNED_BYTE; | |
192 return gles2_rgb_data.Pass(); | |
193 } | |
194 | |
195 scoped_ptr<uint8_t[]> GLES2Data(const Size& size, | |
196 BufferFormat format, | |
197 const uint8_t* data, | |
198 GLenum* data_format, | |
199 GLenum* data_type) { | |
200 switch (format) { | |
201 case BufferFormat::RGBX_8888: | |
202 return GLES2RGBData(size, format, | |
203 data, [](const uint8_t* src, uint8_t* dst) { | |
204 dst[0] = src[0]; | |
205 dst[1] = src[1]; | |
206 dst[2] = src[2]; | |
207 }, data_format, data_type); | |
208 case BufferFormat::BGRX_8888: | |
209 return GLES2RGBData(size, format, | |
210 data, [](const uint8_t* src, uint8_t* dst) { | |
211 dst[0] = src[2]; | |
212 dst[1] = src[1]; | |
213 dst[2] = src[0]; | |
214 }, data_format, data_type); | |
215 case BufferFormat::RGBA_4444: | |
216 case BufferFormat::RGBA_8888: | |
217 case BufferFormat::BGRA_8888: | |
218 case BufferFormat::R_8: | |
219 case BufferFormat::ATC: | |
220 case BufferFormat::ATCIA: | |
221 case BufferFormat::DXT1: | |
222 case BufferFormat::DXT5: | |
223 case BufferFormat::ETC1: | |
224 case BufferFormat::YUV_420: | |
225 case BufferFormat::YUV_420_BIPLANAR: | |
226 case BufferFormat::UYVY_422: | |
227 // No data conversion needed. | |
228 return nullptr; | |
229 } | |
230 | |
231 NOTREACHED(); | |
232 return 0; | |
142 } | 233 } |
143 | 234 |
144 } // namespace | 235 } // namespace |
145 | 236 |
146 GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat) | 237 GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat) |
147 : size_(size), | 238 : size_(size), |
148 internalformat_(internalformat), | 239 internalformat_(internalformat), |
149 memory_(nullptr), | 240 memory_(nullptr), |
150 format_(BufferFormat::RGBA_8888) {} | 241 format_(BufferFormat::RGBA_8888) {} |
151 | 242 |
152 GLImageMemory::~GLImageMemory() { | 243 GLImageMemory::~GLImageMemory() { |
153 DCHECK(!memory_); | 244 DCHECK(!memory_); |
154 } | 245 } |
155 | 246 |
156 // static | |
157 bool GLImageMemory::StrideInBytes(size_t width, | |
158 BufferFormat format, | |
159 size_t* stride_in_bytes) { | |
160 base::CheckedNumeric<size_t> checked_stride = width; | |
161 switch (format) { | |
162 case BufferFormat::ATCIA: | |
163 case BufferFormat::DXT5: | |
164 *stride_in_bytes = width; | |
165 return true; | |
166 case BufferFormat::ATC: | |
167 case BufferFormat::DXT1: | |
168 case BufferFormat::ETC1: | |
169 DCHECK_EQ(width % 2, 0u); | |
170 *stride_in_bytes = width / 2; | |
171 return true; | |
172 case BufferFormat::R_8: | |
173 checked_stride += 3; | |
174 if (!checked_stride.IsValid()) | |
175 return false; | |
176 *stride_in_bytes = checked_stride.ValueOrDie() & ~0x3; | |
177 return true; | |
178 case BufferFormat::RGBA_4444: | |
179 checked_stride *= 2; | |
180 if (!checked_stride.IsValid()) | |
181 return false; | |
182 *stride_in_bytes = checked_stride.ValueOrDie(); | |
183 return true; | |
184 case BufferFormat::RGBA_8888: | |
185 case BufferFormat::BGRA_8888: | |
186 checked_stride *= 4; | |
187 if (!checked_stride.IsValid()) | |
188 return false; | |
189 *stride_in_bytes = checked_stride.ValueOrDie(); | |
190 return true; | |
191 case BufferFormat::BGRX_8888: | |
192 case BufferFormat::YUV_420: | |
193 case BufferFormat::YUV_420_BIPLANAR: | |
194 case BufferFormat::UYVY_422: | |
195 NOTREACHED(); | |
196 return false; | |
197 } | |
198 | |
199 NOTREACHED(); | |
200 return false; | |
201 } | |
202 | |
203 bool GLImageMemory::Initialize(const unsigned char* memory, | 247 bool GLImageMemory::Initialize(const unsigned char* memory, |
204 BufferFormat format) { | 248 BufferFormat format) { |
205 if (!ValidInternalFormat(internalformat_)) { | 249 if (!ValidInternalFormat(internalformat_)) { |
206 LOG(ERROR) << "Invalid internalformat: " << internalformat_; | 250 LOG(ERROR) << "Invalid internalformat: " << internalformat_; |
207 return false; | 251 return false; |
208 } | 252 } |
209 | 253 |
210 if (!ValidFormat(format)) { | 254 if (!ValidFormat(format)) { |
211 LOG(ERROR) << "Invalid format: " << static_cast<int>(format); | 255 LOG(ERROR) << "Invalid format: " << static_cast<int>(format); |
212 return false; | 256 return false; |
(...skipping 27 matching lines...) Expand all Loading... | |
240 bool GLImageMemory::CopyTexImage(unsigned target) { | 284 bool GLImageMemory::CopyTexImage(unsigned target) { |
241 TRACE_EVENT2("gpu", "GLImageMemory::CopyTexImage", "width", size_.width(), | 285 TRACE_EVENT2("gpu", "GLImageMemory::CopyTexImage", "width", size_.width(), |
242 "height", size_.height()); | 286 "height", size_.height()); |
243 | 287 |
244 // GL_TEXTURE_EXTERNAL_OES is not a supported target. | 288 // GL_TEXTURE_EXTERNAL_OES is not a supported target. |
245 if (target == GL_TEXTURE_EXTERNAL_OES) | 289 if (target == GL_TEXTURE_EXTERNAL_OES) |
246 return false; | 290 return false; |
247 | 291 |
248 if (IsCompressedFormat(format_)) { | 292 if (IsCompressedFormat(format_)) { |
249 glCompressedTexImage2D(target, 0, TextureFormat(format_), size_.width(), | 293 glCompressedTexImage2D(target, 0, TextureFormat(format_), size_.width(), |
250 size_.height(), 0, SizeInBytes(size_, format_), | 294 size_.height(), 0, |
251 memory_); | 295 BufferSizeForBufferFormat(size_, format_), memory_); |
252 } else { | 296 } else { |
297 GLenum data_format = DataFormat(format_); | |
298 GLenum data_type = DataType(format_); | |
299 // Note: Conversion of data to a GLES2 supported format is not necessary | |
300 // when using full OpenGL and additional data types are available. To keep | |
301 // things simple, always convert to GLES2 supported format for now. | |
302 scoped_ptr<uint8_t[]> gles2_data = | |
303 GLES2Data(size_, format_, memory_, &data_format, &data_type); | |
304 | |
253 glTexImage2D(target, 0, TextureFormat(format_), size_.width(), | 305 glTexImage2D(target, 0, TextureFormat(format_), size_.width(), |
254 size_.height(), 0, DataFormat(format_), DataType(format_), | 306 size_.height(), 0, data_format, data_type, |
255 memory_); | 307 gles2_data ? gles2_data.get() : memory_); |
256 } | 308 } |
257 | 309 |
258 return true; | 310 return true; |
259 } | 311 } |
260 | 312 |
261 bool GLImageMemory::CopyTexSubImage(unsigned target, | 313 bool GLImageMemory::CopyTexSubImage(unsigned target, |
262 const Point& offset, | 314 const Point& offset, |
263 const Rect& rect) { | 315 const Rect& rect) { |
264 TRACE_EVENT2("gpu", "GLImageMemory::CopyTexSubImage", "width", rect.width(), | 316 TRACE_EVENT2("gpu", "GLImageMemory::CopyTexSubImage", "width", rect.width(), |
265 "height", rect.height()); | 317 "height", rect.height()); |
266 | 318 |
267 // GL_TEXTURE_EXTERNAL_OES is not a supported target. | 319 // GL_TEXTURE_EXTERNAL_OES is not a supported target. |
268 if (target == GL_TEXTURE_EXTERNAL_OES) | 320 if (target == GL_TEXTURE_EXTERNAL_OES) |
269 return false; | 321 return false; |
270 | 322 |
271 // Sub width is not supported. | 323 // Sub width is not supported. |
272 if (rect.width() != size_.width()) | 324 if (rect.width() != size_.width()) |
273 return false; | 325 return false; |
274 | 326 |
275 // Height must be a multiple of 4 if compressed. | 327 // Height must be a multiple of 4 if compressed. |
276 if (IsCompressedFormat(format_) && rect.height() % 4) | 328 if (IsCompressedFormat(format_) && rect.height() % 4) |
277 return false; | 329 return false; |
278 | 330 |
279 size_t stride_in_bytes = 0; | 331 const uint8_t* data = |
280 bool rv = StrideInBytes(size_.width(), format_, &stride_in_bytes); | 332 memory_ + rect.y() * RowSizeForBufferFormat(size_.width(), format_, 0); |
281 DCHECK(rv); | |
282 DCHECK(memory_); | |
283 const unsigned char* data = memory_ + rect.y() * stride_in_bytes; | |
284 if (IsCompressedFormat(format_)) { | 333 if (IsCompressedFormat(format_)) { |
285 glCompressedTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), | 334 glCompressedTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), |
286 rect.height(), DataFormat(format_), | 335 rect.height(), DataFormat(format_), |
287 SizeInBytes(rect.size(), format_), data); | 336 BufferSizeForBufferFormat(rect.size(), format_), |
337 data); | |
288 } else { | 338 } else { |
339 GLenum data_format = DataFormat(format_); | |
340 GLenum data_type = DataType(format_); | |
341 scoped_ptr<uint8_t[]> gles2_data = | |
342 GLES2Data(rect.size(), format_, data, &data_format, &data_type); | |
343 | |
289 glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), | 344 glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), |
290 rect.height(), DataFormat(format_), DataType(format_), | 345 rect.height(), data_format, data_type, |
291 data); | 346 gles2_data ? gles2_data.get() : data); |
292 } | 347 } |
293 | 348 |
294 return true; | 349 return true; |
295 } | 350 } |
296 | 351 |
297 bool GLImageMemory::ScheduleOverlayPlane(AcceleratedWidget widget, | 352 bool GLImageMemory::ScheduleOverlayPlane(AcceleratedWidget widget, |
298 int z_order, | 353 int z_order, |
299 OverlayTransform transform, | 354 OverlayTransform transform, |
300 const Rect& bounds_rect, | 355 const Rect& bounds_rect, |
301 const RectF& crop_rect) { | 356 const RectF& crop_rect) { |
302 return false; | 357 return false; |
303 } | 358 } |
304 | 359 |
360 // static | |
361 unsigned GLImageMemory::GetInternalFormatForTesting(BufferFormat format) { | |
362 DCHECK(ValidFormat(format)); | |
363 return TextureFormat(format); | |
364 } | |
365 | |
305 } // namespace gfx | 366 } // namespace gfx |
OLD | NEW |