glx_util.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright 2020 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/glx_util.h"
  5. #include <unistd.h>
  6. #include "base/compiler_specific.h"
  7. #include "base/logging.h"
  8. #include "base/posix/eintr_wrapper.h"
  9. #include "ui/gfx/linux/native_pixmap_dmabuf.h"
  10. #include "ui/gfx/x/dri3.h"
  11. #include "ui/gfx/x/future.h"
  12. #include "ui/gfx/x/glx.h"
  13. #include "ui/gl/gl_bindings.h"
  14. namespace gl {
  15. namespace {
  16. x11::Glx::FbConfig GetConfigForWindow(x11::Connection* conn,
  17. x11::Window window) {
  18. x11::VisualId visual;
  19. if (auto attrs = conn->GetWindowAttributes({window}).Sync()) {
  20. visual = attrs->visual;
  21. } else {
  22. LOG(ERROR) << "GetWindowAttributes failed for window "
  23. << static_cast<uint32_t>(window) << ".";
  24. return {};
  25. }
  26. if (auto configs =
  27. conn->glx()
  28. .GetFBConfigs({static_cast<uint32_t>(conn->DefaultScreenId())})
  29. .Sync()) {
  30. // The returned property_list is a table consisting of
  31. // 2 * num_FB_configs * num_properties uint32_t's. Each entry in the table
  32. // is a key-value pair. For example, if we have 2 FB configs and 3
  33. // properties, then the table would be laid out as such:
  34. //
  35. // k(c, p) = key for c'th config of p'th property
  36. // v(c, p) = value for c'th config of p'th property
  37. //
  38. // | k(1, 1) | v(1, 1) | k(1, 2) | v(1, 2) | k(1, 3) | v(1, 3) |
  39. // | k(2, 1) | v(2, 1) | k(2, 2) | v(2, 2) | k(2, 3) | v(2, 3) |
  40. auto cfgs = configs->num_FB_configs;
  41. auto props = configs->num_properties;
  42. for (size_t cfg = 0; cfg < cfgs; cfg++) {
  43. x11::Glx::FbConfig fb_config{};
  44. bool found = false;
  45. for (size_t prop = 0; prop < props; prop++) {
  46. size_t i = 2 * cfg * props + 2 * prop;
  47. auto key = configs->property_list[i];
  48. auto value = configs->property_list[i + 1];
  49. if (key == GLX_VISUAL_ID && value == static_cast<uint32_t>(visual))
  50. found = true;
  51. else if (key == GLX_FBCONFIG_ID)
  52. fb_config = static_cast<x11::Glx::FbConfig>(value);
  53. }
  54. if (found)
  55. return fb_config;
  56. }
  57. } else {
  58. LOG(ERROR) << "GetFBConfigs failed.";
  59. return {};
  60. }
  61. return {};
  62. }
  63. int Depth(gfx::BufferFormat format) {
  64. switch (format) {
  65. case gfx::BufferFormat::BGR_565:
  66. return 16;
  67. case gfx::BufferFormat::BGRX_8888:
  68. return 24;
  69. case gfx::BufferFormat::BGRA_1010102:
  70. case gfx::BufferFormat::BGRA_8888:
  71. return 32;
  72. default:
  73. NOTREACHED();
  74. return 0;
  75. }
  76. }
  77. int Bpp(gfx::BufferFormat format) {
  78. switch (format) {
  79. case gfx::BufferFormat::BGR_565:
  80. return 16;
  81. case gfx::BufferFormat::BGRX_8888:
  82. case gfx::BufferFormat::BGRA_1010102:
  83. case gfx::BufferFormat::BGRA_8888:
  84. return 32;
  85. default:
  86. NOTREACHED();
  87. return 0;
  88. }
  89. }
  90. } // namespace
  91. x11::Pixmap XPixmapFromNativePixmap(
  92. const gfx::NativePixmapDmaBuf& native_pixmap,
  93. gfx::BufferFormat buffer_format) {
  94. int depth = Depth(buffer_format);
  95. int bpp = Bpp(buffer_format);
  96. auto fd = HANDLE_EINTR(dup(native_pixmap.GetDmaBufFd(0)));
  97. if (fd < 0)
  98. return x11::Pixmap::None;
  99. x11::RefCountedFD ref_counted_fd(fd);
  100. auto* connection = x11::Connection::Get();
  101. x11::Pixmap pixmap_id = connection->GenerateId<x11::Pixmap>();
  102. // This should be synced. Otherwise, glXCreatePixmap may fail on ChromeOS
  103. // with "failed to create a drawable" error.
  104. connection->dri3()
  105. .PixmapFromBuffer(pixmap_id, connection->default_root(),
  106. native_pixmap.GetDmaBufPlaneSize(0),
  107. native_pixmap.GetBufferSize().width(),
  108. native_pixmap.GetBufferSize().height(),
  109. native_pixmap.GetDmaBufPitch(0), depth, bpp,
  110. ref_counted_fd)
  111. .Sync();
  112. return pixmap_id;
  113. }
  114. GLXFBConfig GetFbConfigForWindow(x11::Connection* connection,
  115. x11::Window window) {
  116. return GetGlxFbConfigForXProtoFbConfig(
  117. connection, GetConfigForWindow(connection, window));
  118. }
  119. GLXFBConfig GetGlxFbConfigForXProtoFbConfig(x11::Connection* connection,
  120. x11::Glx::FbConfig xproto_config) {
  121. if (xproto_config == x11::Glx::FbConfig{})
  122. return nullptr;
  123. int attrib_list[] = {GLX_FBCONFIG_ID, static_cast<int>(xproto_config), 0};
  124. int nitems = 0;
  125. GLXFBConfig* glx_configs =
  126. glXChooseFBConfig(connection->GetXlibDisplay(),
  127. connection->DefaultScreenId(), attrib_list, &nitems);
  128. if (!glx_configs)
  129. return nullptr;
  130. GLXFBConfig glx_config = glx_configs[0];
  131. x11::XlibFree(glx_configs);
  132. return glx_config;
  133. }
  134. } // namespace gl