gl_image_memory.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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
  3. // found in the LICENSE file.
  4. #include "ui/gl/gl_image_memory.h"
  5. #include <stdint.h>
  6. #include "base/barrier_closure.h"
  7. #include "base/logging.h"
  8. #include "base/numerics/checked_math.h"
  9. #include "base/numerics/safe_conversions.h"
  10. #include "base/synchronization/waitable_event.h"
  11. #include "base/system/sys_info.h"
  12. #include "base/task/thread_pool.h"
  13. #include "base/trace_event/trace_event.h"
  14. #include "build/build_config.h"
  15. #include "ui/gfx/buffer_format_util.h"
  16. #include "ui/gfx/gpu_fence.h"
  17. #include "ui/gl/buffer_format_utils.h"
  18. #include "ui/gl/gl_bindings.h"
  19. #include "ui/gl/gl_context.h"
  20. #include "ui/gl/gl_enums.h"
  21. #include "ui/gl/gl_surface.h"
  22. #include "ui/gl/gl_utils.h"
  23. #include "ui/gl/gl_version_info.h"
  24. #include "ui/gl/scoped_binders.h"
  25. #include "ui/gl/scoped_make_current.h"
  26. using gfx::BufferFormat;
  27. namespace gl {
  28. namespace {
  29. GLint DataRowLength(size_t stride, gfx::BufferFormat format) {
  30. switch (format) {
  31. case gfx::BufferFormat::RG_88:
  32. case gfx::BufferFormat::R_16:
  33. case gfx::BufferFormat::BGR_565:
  34. case gfx::BufferFormat::RGBA_4444:
  35. return base::checked_cast<GLint>(stride) / 2;
  36. case gfx::BufferFormat::RG_1616:
  37. case gfx::BufferFormat::RGBX_8888:
  38. case gfx::BufferFormat::RGBA_8888:
  39. case gfx::BufferFormat::BGRX_8888:
  40. case gfx::BufferFormat::BGRA_1010102:
  41. case gfx::BufferFormat::RGBA_1010102:
  42. case gfx::BufferFormat::BGRA_8888:
  43. return base::checked_cast<GLint>(stride) / 4;
  44. case gfx::BufferFormat::RGBA_F16:
  45. return base::checked_cast<GLint>(stride) / 8;
  46. case gfx::BufferFormat::R_8:
  47. return base::checked_cast<GLint>(stride);
  48. case gfx::BufferFormat::YVU_420:
  49. case gfx::BufferFormat::YUV_420_BIPLANAR:
  50. case gfx::BufferFormat::P010:
  51. NOTREACHED() << gfx::BufferFormatToString(format);
  52. return 0;
  53. }
  54. NOTREACHED();
  55. return 0;
  56. }
  57. template <typename F>
  58. std::vector<uint8_t> GLES2RGBData(const gfx::Size& size,
  59. size_t stride,
  60. const uint8_t* data,
  61. F const& data_to_rgb,
  62. GLenum* data_format,
  63. GLenum* data_type,
  64. GLint* data_row_length) {
  65. TRACE_EVENT2("gpu", "GLES2RGBData", "width", size.width(), "height",
  66. size.height());
  67. // Four-byte row alignment as specified by glPixelStorei with argument
  68. // GL_UNPACK_ALIGNMENT set to 4.
  69. size_t gles2_rgb_data_stride = (size.width() * 3 + 3) & ~3;
  70. std::vector<uint8_t> gles2_rgb_data(gles2_rgb_data_stride * size.height());
  71. for (int y = 0; y < size.height(); ++y) {
  72. for (int x = 0; x < size.width(); ++x) {
  73. data_to_rgb(&data[y * stride + x * 4],
  74. &gles2_rgb_data[y * gles2_rgb_data_stride + x * 3]);
  75. }
  76. }
  77. *data_format = GL_RGB;
  78. *data_type = GL_UNSIGNED_BYTE;
  79. *data_row_length = size.width();
  80. return gles2_rgb_data;
  81. }
  82. std::vector<uint8_t> GLES2RGB565Data(const gfx::Size& size,
  83. size_t stride,
  84. const uint8_t* data,
  85. GLenum* data_format,
  86. GLenum* data_type,
  87. GLint* data_row_length) {
  88. TRACE_EVENT2("gpu", "GLES2RGB565Data", "width", size.width(), "height",
  89. size.height());
  90. // Four-byte row alignment as specified by glPixelStorei with argument
  91. // GL_UNPACK_ALIGNMENT set to 4.
  92. size_t gles2_rgb_data_stride = (size.width() * 2 + 3) & ~3;
  93. std::vector<uint8_t> gles2_rgb_data(gles2_rgb_data_stride * size.height());
  94. for (int y = 0; y < size.height(); ++y) {
  95. for (int x = 0; x < size.width(); ++x) {
  96. const uint16_t* src =
  97. reinterpret_cast<const uint16_t*>(&data[y * stride + x * 2]);
  98. uint16_t* dst = reinterpret_cast<uint16_t*>(
  99. &gles2_rgb_data[y * gles2_rgb_data_stride + x * 2]);
  100. *dst = (((*src & 0x1f) >> 0) << 11) | (((*src & 0x7e0) >> 5) << 5) |
  101. (((*src & 0xf800) >> 11) << 5);
  102. }
  103. }
  104. *data_format = GL_RGB;
  105. *data_type = GL_UNSIGNED_SHORT_5_6_5;
  106. *data_row_length = size.width();
  107. return gles2_rgb_data;
  108. }
  109. absl::optional<std::vector<uint8_t>> GLES2Data(const gfx::Size& size,
  110. gfx::BufferFormat format,
  111. size_t stride,
  112. const uint8_t* data,
  113. GLenum* data_format,
  114. GLenum* data_type,
  115. GLint* data_row_length) {
  116. TRACE_EVENT2("gpu", "GLES2Data", "width", size.width(), "height",
  117. size.height());
  118. switch (format) {
  119. case gfx::BufferFormat::RGBX_8888:
  120. return absl::make_optional(GLES2RGBData(
  121. size, stride, data,
  122. [](const uint8_t* src, uint8_t* dst) {
  123. dst[0] = src[0];
  124. dst[1] = src[1];
  125. dst[2] = src[2];
  126. },
  127. data_format, data_type, data_row_length));
  128. case gfx::BufferFormat::BGR_565:
  129. return absl::make_optional(GLES2RGB565Data(
  130. size, stride, data, data_format, data_type, data_row_length));
  131. case gfx::BufferFormat::BGRX_8888:
  132. return absl::make_optional(GLES2RGBData(
  133. size, stride, data,
  134. [](const uint8_t* src, uint8_t* dst) {
  135. dst[0] = src[2];
  136. dst[1] = src[1];
  137. dst[2] = src[0];
  138. },
  139. data_format, data_type, data_row_length));
  140. case gfx::BufferFormat::RGBA_4444:
  141. case gfx::BufferFormat::RGBA_8888:
  142. case gfx::BufferFormat::BGRA_1010102:
  143. case gfx::BufferFormat::RGBA_1010102:
  144. case gfx::BufferFormat::BGRA_8888:
  145. case gfx::BufferFormat::RGBA_F16:
  146. case gfx::BufferFormat::R_8:
  147. case gfx::BufferFormat::R_16:
  148. case gfx::BufferFormat::RG_88:
  149. case gfx::BufferFormat::RG_1616: {
  150. size_t gles2_data_stride =
  151. RowSizeForBufferFormat(size.width(), format, 0);
  152. if (stride == gles2_data_stride ||
  153. g_current_gl_driver->ext.b_GL_EXT_unpack_subimage)
  154. return absl::nullopt; // No data conversion needed
  155. std::vector<uint8_t> gles2_data(gles2_data_stride * size.height());
  156. for (int y = 0; y < size.height(); ++y) {
  157. memcpy(&gles2_data[y * gles2_data_stride], &data[y * stride],
  158. gles2_data_stride);
  159. }
  160. *data_row_length = size.width();
  161. return absl::make_optional(gles2_data);
  162. }
  163. case gfx::BufferFormat::YVU_420:
  164. case gfx::BufferFormat::YUV_420_BIPLANAR:
  165. case gfx::BufferFormat::P010:
  166. NOTREACHED() << gfx::BufferFormatToString(format);
  167. return absl::nullopt;
  168. }
  169. NOTREACHED();
  170. return absl::nullopt;
  171. }
  172. void MemcpyTask(const void* src,
  173. void* dst,
  174. size_t bytes,
  175. size_t task_index,
  176. size_t n_tasks,
  177. base::RepeatingClosure* done) {
  178. auto checked_bytes = base::CheckedNumeric<size_t>(bytes);
  179. size_t start = (checked_bytes * task_index / n_tasks).ValueOrDie();
  180. size_t end = (checked_bytes * (task_index + 1) / n_tasks).ValueOrDie();
  181. DCHECK_LE(start, bytes);
  182. DCHECK_LE(end, bytes);
  183. memcpy(static_cast<char*>(dst) + start, static_cast<const char*>(src) + start,
  184. end - start);
  185. done->Run();
  186. }
  187. bool SupportsPBO(GLContext* context) {
  188. const GLVersionInfo* version = context->GetVersionInfo();
  189. return version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0) ||
  190. context->HasExtension("GL_ARB_pixel_buffer_object") ||
  191. context->HasExtension("GL_EXT_pixel_buffer_object") ||
  192. context->HasExtension("GL_NV_pixel_buffer_object");
  193. }
  194. bool SupportsMapBuffer(GLContext* context) {
  195. return context->GetVersionInfo()->IsAtLeastGL(2, 0) ||
  196. context->HasExtension("GL_OES_mapbuffer");
  197. }
  198. bool SupportsMapBufferRange(GLContext* context) {
  199. return context->GetVersionInfo()->IsAtLeastGLES(3, 0) ||
  200. context->HasExtension("GL_EXT_map_buffer_range");
  201. }
  202. } // namespace
  203. GLImageMemory::GLImageMemory(const gfx::Size& size)
  204. : size_(size),
  205. memory_(nullptr),
  206. format_(gfx::BufferFormat::RGBA_8888),
  207. stride_(0) {}
  208. GLImageMemory::~GLImageMemory() {
  209. if (buffer_ && original_context_ && original_surface_) {
  210. ui::ScopedMakeCurrent make_current(original_context_.get(),
  211. original_surface_.get());
  212. glDeleteBuffersARB(1, &buffer_);
  213. }
  214. }
  215. // static
  216. GLImageMemory* GLImageMemory::FromGLImage(GLImage* image) {
  217. if (!image || image->GetType() != Type::MEMORY)
  218. return nullptr;
  219. return static_cast<GLImageMemory*>(image);
  220. }
  221. bool GLImageMemory::Initialize(const unsigned char* memory,
  222. gfx::BufferFormat format,
  223. size_t stride) {
  224. if (!ValidFormat(format)) {
  225. LOG(ERROR) << "Invalid format: " << gfx::BufferFormatToString(format);
  226. return false;
  227. }
  228. if (stride < RowSizeForBufferFormat(size_.width(), format, 0) || stride & 3) {
  229. LOG(ERROR) << "Invalid stride: " << stride;
  230. return false;
  231. }
  232. DCHECK(memory);
  233. DCHECK(!memory_);
  234. memory_ = memory;
  235. format_ = format;
  236. stride_ = stride;
  237. bool tex_image_from_pbo_is_slow = false;
  238. #if BUILDFLAG(IS_WIN)
  239. tex_image_from_pbo_is_slow = true;
  240. #endif // BUILDFLAG(IS_WIN)
  241. GLContext* context = GLContext::GetCurrent();
  242. DCHECK(context);
  243. if (!tex_image_from_pbo_is_slow && SupportsPBO(context) &&
  244. (SupportsMapBuffer(context) || SupportsMapBufferRange(context))) {
  245. constexpr size_t kTaskBytes = 1024 * 1024;
  246. buffer_bytes_ = stride * size_.height();
  247. memcpy_tasks_ = std::min<size_t>(buffer_bytes_ / kTaskBytes,
  248. base::SysInfo::NumberOfProcessors());
  249. if (memcpy_tasks_ > 1) {
  250. glGenBuffersARB(1, &buffer_);
  251. ScopedBufferBinder binder(GL_PIXEL_UNPACK_BUFFER, buffer_);
  252. glBufferData(GL_PIXEL_UNPACK_BUFFER, buffer_bytes_, nullptr,
  253. GL_DYNAMIC_DRAW);
  254. original_context_ = context->AsWeakPtr();
  255. GLSurface* surface = GLSurface::GetCurrent();
  256. DCHECK(surface);
  257. original_surface_ = surface->AsWeakPtr();
  258. }
  259. }
  260. return true;
  261. }
  262. gfx::Size GLImageMemory::GetSize() {
  263. return size_;
  264. }
  265. unsigned GLImageMemory::GetInternalFormat() {
  266. return gl::BufferFormatToGLInternalFormat(format_);
  267. }
  268. unsigned GLImageMemory::GetDataFormat() {
  269. switch (format_) {
  270. case gfx::BufferFormat::RGBX_8888:
  271. case gfx::BufferFormat::RGBA_1010102:
  272. return GL_RGBA;
  273. case gfx::BufferFormat::BGRX_8888:
  274. case gfx::BufferFormat::BGRA_1010102:
  275. return GL_BGRA_EXT;
  276. default:
  277. break;
  278. }
  279. return GLImage::GetDataFormat();
  280. }
  281. unsigned GLImageMemory::GetDataType() {
  282. switch (format_) {
  283. case gfx::BufferFormat::BGR_565:
  284. return GL_UNSIGNED_SHORT_5_6_5_REV;
  285. default:
  286. break;
  287. }
  288. return gl::BufferFormatToGLDataType(format_);
  289. }
  290. GLImage::BindOrCopy GLImageMemory::ShouldBindOrCopy() {
  291. return COPY;
  292. }
  293. bool GLImageMemory::BindTexImage(unsigned target) {
  294. NOTREACHED();
  295. return false;
  296. }
  297. bool GLImageMemory::CopyTexImage(unsigned target) {
  298. TRACE_EVENT2("gpu", "GLImageMemory::CopyTexImage", "width", size_.width(),
  299. "height", size_.height());
  300. if (target == GL_TEXTURE_EXTERNAL_OES)
  301. return false;
  302. GLenum data_format = GetDataFormat();
  303. GLenum data_type = GetDataType();
  304. GLint data_row_length = DataRowLength(stride_, format_);
  305. absl::optional<std::vector<uint8_t>> gles2_data;
  306. GLContext* context = GLContext::GetCurrent();
  307. DCHECK(context);
  308. if (context->GetVersionInfo()->is_es) {
  309. gles2_data = GLES2Data(size_, format_, stride_, memory_, &data_format,
  310. &data_type, &data_row_length);
  311. }
  312. ScopedPixelStore scoped_unpack_row_length(
  313. GL_UNPACK_ROW_LENGTH,
  314. data_row_length == size_.width() ? 0 : data_row_length);
  315. ScopedPixelStore scoped_unpack_skip_pixels(GL_UNPACK_SKIP_PIXELS, 0);
  316. ScopedPixelStore scoped_unpack_skip_rows(GL_UNPACK_SKIP_ROWS, 0);
  317. ScopedPixelStore scoped_unpack_alignment(GL_UNPACK_ALIGNMENT, 4);
  318. const void* src;
  319. size_t size;
  320. if (gles2_data) {
  321. src = gles2_data->data();
  322. size = gles2_data->size();
  323. } else {
  324. src = memory_;
  325. size = buffer_bytes_;
  326. }
  327. bool uploaded = false;
  328. if (buffer_ && original_context_.get() == context) {
  329. glTexImage2D(target, 0, GetInternalFormat(), size_.width(), size_.height(),
  330. 0, data_format, data_type, nullptr);
  331. ScopedBufferBinder binder(GL_PIXEL_UNPACK_BUFFER, buffer_);
  332. void* dst = nullptr;
  333. if (SupportsMapBuffer(context)) {
  334. dst = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
  335. } else {
  336. DCHECK(SupportsMapBufferRange(context));
  337. dst = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, size, GL_MAP_WRITE_BIT);
  338. }
  339. if (dst) {
  340. base::WaitableEvent event;
  341. base::RepeatingClosure barrier = base::BarrierClosure(
  342. memcpy_tasks_, base::BindOnce(&base::WaitableEvent::Signal,
  343. base::Unretained(&event)));
  344. for (int i = 1; i < memcpy_tasks_; ++i) {
  345. base::ThreadPool::PostTask(
  346. FROM_HERE, base::BindOnce(&MemcpyTask, src, dst, size, i,
  347. memcpy_tasks_, &barrier));
  348. }
  349. MemcpyTask(src, dst, size, 0, memcpy_tasks_, &barrier);
  350. event.Wait();
  351. glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
  352. glTexSubImage2D(target, 0, 0, 0, size_.width(), size_.height(),
  353. data_format, data_type, 0);
  354. uploaded = true;
  355. } else {
  356. glDeleteBuffersARB(1, &buffer_);
  357. buffer_ = 0;
  358. }
  359. }
  360. if (!uploaded) {
  361. glTexImage2D(target, 0, GetInternalFormat(), size_.width(), size_.height(),
  362. 0, data_format, data_type, src);
  363. }
  364. return true;
  365. }
  366. bool GLImageMemory::CopyTexSubImage(unsigned target,
  367. const gfx::Point& offset,
  368. const gfx::Rect& rect) {
  369. TRACE_EVENT2("gpu", "GLImageMemory::CopyTexSubImage", "width", rect.width(),
  370. "height", rect.height());
  371. // GL_TEXTURE_EXTERNAL_OES is not a supported target.
  372. if (target == GL_TEXTURE_EXTERNAL_OES)
  373. return false;
  374. // Sub width is not supported.
  375. if (rect.width() != size_.width())
  376. return false;
  377. const uint8_t* data = memory_ + rect.y() * stride_;
  378. GLenum data_format = GetDataFormat();
  379. GLenum data_type = GetDataType();
  380. GLint data_row_length = DataRowLength(stride_, format_);
  381. absl::optional<std::vector<uint8_t>> gles2_data;
  382. if (GLContext::GetCurrent()->GetVersionInfo()->is_es) {
  383. gles2_data = GLES2Data(rect.size(), format_, stride_, data, &data_format,
  384. &data_type, &data_row_length);
  385. }
  386. ScopedPixelStore scoped_unpack_row_length(
  387. GL_UNPACK_ROW_LENGTH,
  388. data_row_length == rect.width() ? 0 : data_row_length);
  389. ScopedPixelStore scoped_unpack_skip_pixels(GL_UNPACK_SKIP_PIXELS, 0);
  390. ScopedPixelStore scoped_unpack_skip_rows(GL_UNPACK_SKIP_ROWS, 0);
  391. ScopedPixelStore scoped_unpack_alignment(GL_UNPACK_ALIGNMENT, 4);
  392. glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(),
  393. rect.height(), data_format, data_type,
  394. gles2_data ? gles2_data->data() : data);
  395. return true;
  396. }
  397. GLImageMemory::Type GLImageMemory::GetType() const {
  398. return Type::MEMORY;
  399. }
  400. // static
  401. bool GLImageMemory::ValidFormat(gfx::BufferFormat format) {
  402. switch (format) {
  403. case gfx::BufferFormat::R_8:
  404. case gfx::BufferFormat::R_16:
  405. case gfx::BufferFormat::RG_88:
  406. case gfx::BufferFormat::RG_1616:
  407. case gfx::BufferFormat::BGR_565:
  408. case gfx::BufferFormat::RGBA_4444:
  409. case gfx::BufferFormat::RGBX_8888:
  410. case gfx::BufferFormat::RGBA_8888:
  411. case gfx::BufferFormat::BGRX_8888:
  412. case gfx::BufferFormat::BGRA_1010102:
  413. case gfx::BufferFormat::RGBA_1010102:
  414. case gfx::BufferFormat::BGRA_8888:
  415. case gfx::BufferFormat::RGBA_F16:
  416. return true;
  417. case gfx::BufferFormat::YVU_420:
  418. case gfx::BufferFormat::YUV_420_BIPLANAR:
  419. case gfx::BufferFormat::P010:
  420. return false;
  421. }
  422. NOTREACHED();
  423. return false;
  424. }
  425. } // namespace gl