| 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/gl_image_ozone_native_pixmap.h" |
| 18 #include "ui/gl/test/gl_image_test_template.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 { // Check we have permissions |
| 47 drm_magic_t magic{}; |
| 48 bool ret = !drmGetMagic(drm_fd.get(), &magic) && |
| 49 !drmAuthMagic(drm_fd.get(), magic); |
| 50 DCHECK(ret); |
| 51 } |
| 52 |
| 53 std::vector<int> pitches{RoundTo64(size.width()), RoundTo64(size.width() / 2), |
| 54 RoundTo64(size.width() / 2)}; |
| 55 std::vector<int> offsets{ |
| 56 0, pitches[0] * size.height() + pitches[1] * size.height() / 2, |
| 57 pitches[0] * size.height(), |
| 58 }; |
| 59 size_t byte_number = offsets[2] + pitches[2] * size.height() / 2; |
| 60 |
| 61 struct drm_i915_gem_create gem_create {}; |
| 62 gem_create.size = byte_number; |
| 63 int ret = drmIoctl(drm_fd.get(), DRM_IOCTL_I915_GEM_CREATE, &gem_create); |
| 64 DCHECK(!ret) << "Can't create the GEM buffer."; |
| 65 struct drm_i915_gem_set_tiling gem_set_tiling {}; |
| 66 do { |
| 67 gem_set_tiling.handle = gem_create.handle; |
| 68 gem_set_tiling.tiling_mode = I915_TILING_NONE; |
| 69 ret = |
| 70 drmIoctl(drm_fd.get(), DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling); |
| 71 } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); |
| 72 DCHECK_NE(-1, ret); |
| 73 int fd = -1; |
| 74 drmPrimeHandleToFD(drm_fd.get(), gem_create.handle, DRM_CLOEXEC, &fd); |
| 75 EXPECT_NE(-1, fd); |
| 76 |
| 77 std::vector<uint8_t> data(byte_number); |
| 78 for (int plane = 0; plane < 3; ++plane) { |
| 79 GLImageTestSupport::SetBufferDataToColor( |
| 80 size.width(), size.height(), pitches[plane], plane, |
| 81 gfx::BufferFormat::YVU_420, kImageColor, &data[offsets[plane]]); |
| 82 } |
| 83 |
| 84 // TODO(dcastagna): Add support for mapping planar formats with |
| 85 // ClientNativePixmap and remove this code. |
| 86 struct drm_i915_gem_pwrite gem_pwrite {}; |
| 87 gem_pwrite.handle = gem_create.handle; |
| 88 gem_pwrite.size = byte_number; |
| 89 gem_pwrite.data_ptr = reinterpret_cast<uint64_t>(&data[0]); |
| 90 ret = drmIoctl(drm_fd.get(), DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite); |
| 91 DCHECK(!ret) << "Problems with drmIoctl when writing data."; |
| 92 |
| 93 gfx::NativePixmapHandle pixmap_handle; |
| 94 pixmap_handle.fds.emplace_back(fd, false); |
| 95 for (int i = 0; i < 3; i++) { |
| 96 pixmap_handle.strides_and_offsets.emplace_back(pitches[i], offsets[i]); |
| 97 } |
| 98 ui::SurfaceFactoryOzone* surface_factory = |
| 99 ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone(); |
| 100 return surface_factory->CreateNativePixmapFromHandle( |
| 101 size, gfx::BufferFormat::YVU_420, pixmap_handle); |
| 102 } |
| 103 |
| 104 // Delegate to test EGL images created directly using drm. |
| 105 // YVU420 buffers can't be created yet via Ozone, we still |
| 106 // want to test them since they can be imported and displayed |
| 107 // via exo. |
| 108 // TODO(dcastagna): once it's possible to allocate and map YV12 format |
| 109 // using Ozone merge this test with GLImageOzoneNativePixmapTestDelegate. |
| 110 class GLImageOzoneNativePixmapDrmTestDelegate { |
| 111 public: |
| 112 GLImageOzoneNativePixmapDrmTestDelegate() {} |
| 113 scoped_refptr<GLImage> CreateSolidColorImage(const gfx::Size& size, |
| 114 const uint8_t color[4]) const { |
| 115 scoped_refptr<ui::NativePixmap> pixmap = CreateYVU420Pixmap(size, color); |
| 116 |
| 117 scoped_refptr<GLImageOzoneNativePixmap> image( |
| 118 new GLImageOzoneNativePixmap(size, GL_RGB_YCRCB_420_CHROMIUM)); |
| 119 EXPECT_TRUE(image->Initialize(pixmap.get(), pixmap->GetBufferFormat())); |
| 120 return image; |
| 121 } |
| 122 |
| 123 unsigned GetTextureTarget() const { return GL_TEXTURE_EXTERNAL_OES; } |
| 124 |
| 125 const uint8_t* GetImageColor() { return kImageColor; } |
| 126 |
| 127 private: |
| 128 }; |
| 129 |
| 130 INSTANTIATE_TYPED_TEST_CASE_P(GLImageOzoneNativePixmapDrm, |
| 131 GLImageTest, |
| 132 GLImageOzoneNativePixmapDrmTestDelegate); |
| 133 |
| 134 INSTANTIATE_TYPED_TEST_CASE_P(GLImageOzoneNativePixmapDrm, |
| 135 GLImageBindTest, |
| 136 GLImageOzoneNativePixmapDrmTestDelegate); |
| 137 |
| 138 } // namespace |
| 139 } // namespace gl |
| OLD | NEW |