OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 | |
5 #include <fcntl.h> | |
6 #include <libdrm/i915_drm.h> | |
7 #include <linux/types.h> | |
8 #include <stdint.h> | |
9 #include <stdio.h> | |
10 #include <sys/mman.h> | |
11 #include <xf86drm.h> | |
12 | |
13 #include "base/files/scoped_file.h" | |
14 #include "base/posix/eintr_wrapper.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 #include "ui/gfx/buffer_types.h" | |
17 #include "ui/gl/test/gl_image_test_template.h" | |
18 #include "ui/ozone/gl/gl_image_ozone_native_pixmap.h" | |
19 #include "ui/ozone/public/ozone_platform.h" | |
20 #include "ui/ozone/public/surface_factory_ozone.h" | |
21 | |
22 namespace gl { | |
23 namespace { | |
24 | |
25 // These values are picked so that RGB -> YVU on the CPU converted | |
26 // back to RGB on the GPU produces the original RGB values without | |
27 // any error. | |
28 const uint8_t kImageColor[] = {0x10, 0x20, 0, 0xFF}; | |
29 | |
30 // Round |num| up to 64. | |
31 int RoundTo64(int num) { | |
32 return (num + 63) & ~63; | |
33 } | |
34 | |
35 // Create a YVU420 NativePixmap using the drm interface directly. | |
36 scoped_refptr<ui::NativePixmap> CreateYVU420Pixmap(const gfx::Size& size, | |
37 const uint8_t color[4]) { | |
38 DCHECK_EQ(0, size.width() % 2); | |
39 DCHECK_EQ(0, size.height() % 2); | |
40 | |
41 // TODO(dcastagna): move the creation of the drmbuf to minigmb, where it's | |
42 // supposed to be, so we can abastract it and use SurfaceFactoryOzone. | |
43 base::ScopedFD drm_fd( | |
44 HANDLE_EINTR(open("/dev/dri/card0", O_RDWR | O_CLOEXEC))); | |
45 DCHECK(drm_fd.is_valid()) << "Couldn't open '/dev/dri/card0'"; | |
46 | |
47 std::vector<int> pitches{RoundTo64(size.width()), RoundTo64(size.width() / 2), | |
48 RoundTo64(size.width() / 2)}; | |
49 std::vector<int> offsets{ | |
50 0, pitches[0] * size.height() + pitches[1] * size.height() / 2, | |
51 pitches[0] * size.height(), | |
52 }; | |
53 size_t byte_number = pitches[0] * size.height() + | |
54 pitches[1] * size.height() / 2 + | |
55 pitches[2] * size.height() / 2; | |
56 | |
57 struct drm_i915_gem_create gem_create {}; | |
58 gem_create.size = byte_number; | |
59 int ret = drmIoctl(drm_fd.get(), DRM_IOCTL_I915_GEM_CREATE, &gem_create); | |
60 DCHECK(!ret) << "Can't create the GEM buffer."; | |
61 struct drm_i915_gem_set_tiling gem_set_tiling {}; | |
62 do { | |
63 gem_set_tiling.handle = gem_create.handle; | |
64 gem_set_tiling.tiling_mode = I915_TILING_NONE; | |
65 ret = | |
66 drmIoctl(drm_fd.get(), DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling); | |
67 } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); | |
68 DCHECK_NE(-1, ret); | |
69 int fd = -1; | |
70 drmPrimeHandleToFD(drm_fd.get(), gem_create.handle, DRM_CLOEXEC, &fd); | |
71 EXPECT_NE(-1, fd); | |
72 | |
73 std::vector<uint8_t> data(byte_number); | |
74 for (int plane = 0; plane < 3; ++plane) { | |
75 GLImageTestSupport::SetBufferDataToColor( | |
76 size.width(), size.height(), pitches[plane], plane, | |
77 gfx::BufferFormat::YVU_420, kImageColor, &data[offsets[plane]]); | |
78 } | |
79 | |
80 // TODO(dcastagna): Add support for mapping planar formats with | |
81 // ClientNativePixmap and remove this code. | |
82 struct drm_i915_gem_pwrite gem_pwrite {}; | |
83 gem_pwrite.handle = gem_create.handle; | |
84 gem_pwrite.size = byte_number; | |
85 gem_pwrite.data_ptr = reinterpret_cast<uint64_t>(&data[0]); | |
86 ret = drmIoctl(drm_fd.get(), DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite); | |
87 DCHECK(!ret) << "Problems with drmIoctl when writing data."; | |
88 | |
89 gfx::NativePixmapHandle pixmap_handle; | |
90 pixmap_handle.fds.emplace_back(fd, false); | |
91 for (int i = 0; i < 3; i++) { | |
92 pixmap_handle.planes.emplace_back(pitches[i], offsets[i], 0); | |
93 } | |
94 ui::SurfaceFactoryOzone* surface_factory = | |
95 ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone(); | |
96 return surface_factory->CreateNativePixmapFromHandle( | |
97 gfx::kNullAcceleratedWidget, size, gfx::BufferFormat::YVU_420, | |
98 pixmap_handle); | |
99 } | |
100 | |
101 // Delegate to test EGL images created directly using drm. | |
102 // YVU420 buffers can't be created yet via Ozone, we still | |
103 // want to test them since they can be imported and displayed | |
104 // via exo. | |
105 // TODO(dcastagna): once it's possible to allocate and map YV12 format | |
106 // using Ozone merge this test with GLImageOzoneNativePixmapTestDelegate. | |
107 class GLImageOzoneNativePixmapDrmTestDelegate { | |
108 public: | |
109 GLImageOzoneNativePixmapDrmTestDelegate() {} | |
110 scoped_refptr<GLImage> CreateSolidColorImage(const gfx::Size& size, | |
111 const uint8_t color[4]) const { | |
112 scoped_refptr<ui::NativePixmap> pixmap = CreateYVU420Pixmap(size, color); | |
113 | |
114 scoped_refptr<ui::GLImageOzoneNativePixmap> image( | |
115 new ui::GLImageOzoneNativePixmap(size, GL_RGB_YCRCB_420_CHROMIUM)); | |
116 EXPECT_TRUE(image->Initialize(pixmap.get(), pixmap->GetBufferFormat())); | |
117 return image; | |
118 } | |
119 | |
120 unsigned GetTextureTarget() const { return GL_TEXTURE_EXTERNAL_OES; } | |
121 | |
122 const uint8_t* GetImageColor() { return kImageColor; } | |
123 | |
124 private: | |
125 }; | |
126 | |
127 | |
128 // TODO(crbug.com/618516) - The tests in this file can only be run | |
129 // on a real device, and not on linux desktop builds, so they are | |
130 // disabled until they can correctly detect the environment and do | |
131 INSTANTIATE_TYPED_TEST_CASE_P(DISABLED_GLImageOzoneNativePixmapDrm, | |
132 GLImageTest, | |
133 GLImageOzoneNativePixmapDrmTestDelegate); | |
134 | |
135 INSTANTIATE_TYPED_TEST_CASE_P(DISABLED_GLImageOzoneNativePixmapDrm, | |
136 GLImageBindTest, | |
137 GLImageOzoneNativePixmapDrmTestDelegate); | |
138 | |
139 } // namespace | |
140 } // namespace gl | |
OLD | NEW |