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