| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 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 |
| 5 #include "content/browser/gpu/dri_buffer_manager.h" |
| 6 |
| 7 extern "C" { |
| 8 #include <fcntl.h> |
| 9 #include </home/marius/mesa_ander/src/gbm/main/gbm.h> |
| 10 #include <sys/mman.h> |
| 11 #include <unistd.h> |
| 12 #include <X11/Xlib.h> |
| 13 #include <X11/Xlibint.h> |
| 14 #include <X11/extensions/Xext.h> |
| 15 #include <X11/extensions/extutil.h> |
| 16 #include <X11/X.h> |
| 17 #include <X11/Xproto.h> |
| 18 #include <X11/extensions/dri2proto.h> |
| 19 #include <xf86drm.h> |
| 20 } |
| 21 |
| 22 #include "base/logging.h" |
| 23 #include "ui/gfx/x/x11_types.h" |
| 24 //#define USE_DMA_BUF_MMAP |
| 25 //#define __DEBUG__ |
| 26 namespace content { |
| 27 |
| 28 const char kDefaultGraphicsCardPath[] = "/dev/dri/card0"; |
| 29 static char dri2ExtensionName[] = DRI2_NAME; |
| 30 static XExtensionInfo *dri2Info; |
| 31 static XEXT_GENERATE_CLOSE_DISPLAY(DRI2CloseDisplay, dri2Info) |
| 32 static /* const */ XExtensionHooks dri2ExtensionHooks = { |
| 33 NULL, // create_gc |
| 34 NULL, // copy_gc |
| 35 NULL, // flush_gc |
| 36 NULL, // free_gc |
| 37 NULL, // create_font |
| 38 NULL, // free_font |
| 39 DRI2CloseDisplay, // close_display |
| 40 NULL, // wire_to_event |
| 41 NULL, // event_to_wire |
| 42 NULL, // error |
| 43 NULL, // error_string |
| 44 }; |
| 45 |
| 46 static XEXT_GENERATE_FIND_DISPLAY(DRI2FindDisplay, dri2Info, |
| 47 dri2ExtensionName, |
| 48 &dri2ExtensionHooks, |
| 49 0, |
| 50 NULL) |
| 51 int DRIBufferManager::fd_ = 0; |
| 52 struct gbm_device* DRIBufferManager::gbm_ = NULL; |
| 53 |
| 54 DRIBufferManager::DRIBufferManager() /*: fd_(0), |
| 55 gbm_(NULL)*/ { |
| 56 AuthConnection(); |
| 57 } |
| 58 |
| 59 DRIBufferManager::~DRIBufferManager() { |
| 60 if (gbm_) |
| 61 gbm_device_destroy(gbm_); |
| 62 close(fd_); |
| 63 } |
| 64 |
| 65 void DRIBufferManager::CreateBuffer(int width, |
| 66 int height, |
| 67 gfx::GpuMemoryBufferHandle& handle) { |
| 68 //DCHECK(fd_); |
| 69 if (fd_ <= 0) { |
| 70 if(!AuthConnection()) { |
| 71 fprintf(stderr, "\nAuthConnection failed!\n"); |
| 72 return; |
| 73 } |
| 74 fprintf(stderr, "\n CONNECTION ready!\n"); |
| 75 } |
| 76 if (!gbm_) { |
| 77 gbm_ = gbm_create_device(fd_); |
| 78 //fprintf(stderr, "\nGBM CREATED %d\n", fd_); |
| 79 if (!gbm_) { |
| 80 LOG(ERROR) << "DRIBufferManager: Failed to create GBM device."; |
| 81 return; |
| 82 } |
| 83 } |
| 84 #if defined(USE_DMA_BUF_MMAP) |
| 85 if (!IsMmapSupported()) { |
| 86 fprintf(stderr, "\nMMAP Is NOT SUPPORTED!\n"); |
| 87 fflush(stderr); |
| 88 return; |
| 89 } |
| 90 #endif |
| 91 // TODO(kalyan): how do we free this buffer? |
| 92 struct gbm_bo* tex_bo = gbm_bo_create(gbm_, |
| 93 width, |
| 94 height, |
| 95 GBM_BO_FORMAT_ARGB8888, |
| 96 GBM_BO_USE_MAP); |
| 97 if (!tex_bo) { |
| 98 LOG(ERROR) << "DRIBufferManager: Failed to allocate buffer."; |
| 99 fprintf(stderr, "\nDRIBufferManager: Failed to allocate buffer."); |
| 100 return; |
| 101 } |
| 102 |
| 103 int dma_buf_handle; |
| 104 /* |
| 105 gbm_bo_export(tex_bo, |
| 106 GBM_BO_IMPORT_DMA_BUF, |
| 107 reinterpret_cast<void**>(&dma_buf_handle), |
| 108 GBM_BO_USE_MAP); |
| 109 */ |
| 110 dma_buf_handle = gbm_bo_get_fd(tex_bo); |
| 111 handle.type = gfx::DMA_BUFFER; |
| 112 handle.card_handle.fd = fd_; |
| 113 handle.handle.fd = dma_buf_handle; |
| 114 handle.stride = gbm_bo_get_stride(tex_bo); |
| 115 DCHECK( handle.stride > width); |
| 116 |
| 117 #ifdef __DEBUG__ |
| 118 fprintf(stderr, "\nDRIBufferManager::CreateBuffer(%d,%d,%d)=%d\n", width, he
ight, handle.stride, dma_buf_handle); |
| 119 fflush(stderr); |
| 120 #endif |
| 121 |
| 122 } |
| 123 |
| 124 bool DRIBufferManager::AuthConnection() { |
| 125 // TODO(Kalyan): we would need to check for dri3 support when using GLX. |
| 126 fd_ = open(kDefaultGraphicsCardPath, O_RDWR); |
| 127 if (fd_ <= 0) { |
| 128 return false; |
| 129 } |
| 130 |
| 131 drm_magic_t magic; |
| 132 if (drmGetMagic(fd_, &magic)) { |
| 133 close(fd_); |
| 134 return false; |
| 135 } |
| 136 |
| 137 Display *dpy = reinterpret_cast<Display *>(gfx::GetXDisplay()); |
| 138 XExtDisplayInfo *info = DRI2FindDisplay(dpy); |
| 139 xDRI2AuthenticateReq *req; |
| 140 xDRI2AuthenticateReply rep; |
| 141 |
| 142 XextCheckExtension(dpy, info, dri2ExtensionName, False); |
| 143 LockDisplay(dpy); |
| 144 GetReq(DRI2Authenticate, req); |
| 145 req->reqType = info->codes->major_opcode; |
| 146 req->dri2ReqType = X_DRI2Authenticate; |
| 147 req->magic = magic; |
| 148 req->window = DefaultRootWindow(dpy); |
| 149 if (!_XReply(dpy, reinterpret_cast<xReply *>(&rep), 0, xFalse)) { |
| 150 UnlockDisplay(dpy); |
| 151 SyncHandle(); |
| 152 return false; |
| 153 } |
| 154 |
| 155 UnlockDisplay(dpy); |
| 156 SyncHandle(); |
| 157 |
| 158 if (!rep.authenticated) { |
| 159 close(fd_); |
| 160 return false; |
| 161 } |
| 162 |
| 163 return true; |
| 164 } |
| 165 |
| 166 bool DRIBufferManager::IsMmapSupported() { |
| 167 static bool dma_buf_mmap_supported = true; |
| 168 static bool check_done = false; |
| 169 if (check_done) |
| 170 return dma_buf_mmap_supported; |
| 171 |
| 172 fprintf(stderr, "\nCHECK!\n"); |
| 173 fflush(stderr); |
| 174 check_done = true; |
| 175 struct gbm_bo* temp_bo = gbm_bo_create(gbm_, |
| 176 1, |
| 177 1, |
| 178 GBM_BO_FORMAT_ARGB8888, |
| 179 GBM_BO_USE_MAP); |
| 180 |
| 181 int temp; |
| 182 /* |
| 183 gbm_bo_export(temp_bo, |
| 184 GBM_BO_IMPORT_DMA_BUF, |
| 185 reinterpret_cast<void**>(&temp), |
| 186 GBM_BO_USE_MAP); |
| 187 */ |
| 188 temp = gbm_bo_get_fd(temp_bo); |
| 189 |
| 190 int stride = gbm_bo_get_stride(temp_bo); |
| 191 |
| 192 // Check if platform supports mmap with proc_read. |
| 193 if (!MmapDmaBuf(temp, PROT_READ, stride)) { |
| 194 LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf" |
| 195 << "handle with PROT_READ."; |
| 196 dma_buf_mmap_supported = false; |
| 197 } |
| 198 |
| 199 // Check if platform supports mmap with proc_write. |
| 200 if (!MmapDmaBuf(temp, PROT_WRITE, stride)) { |
| 201 LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf" |
| 202 << "handle with PROT_WRITE."; |
| 203 dma_buf_mmap_supported = false; |
| 204 } |
| 205 |
| 206 // Check if platform supports mmap with proc_write and proc_read. |
| 207 |
| 208 if (!MmapDmaBuf(temp, (PROT_READ | PROT_WRITE), stride)) { |
| 209 LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf" |
| 210 << "handle with PROT_READ | PROT_WRITE."; |
| 211 dma_buf_mmap_supported = false; |
| 212 } |
| 213 |
| 214 gbm_bo_destroy(temp_bo); |
| 215 close(temp); |
| 216 return dma_buf_mmap_supported; |
| 217 } |
| 218 |
| 219 bool DRIBufferManager::MmapDmaBuf(int dma_buf_id, int proc, int stride) { |
| 220 void* temp_map = mmap(NULL, |
| 221 stride, |
| 222 proc, |
| 223 MAP_SHARED, |
| 224 dma_buf_id, |
| 225 0); |
| 226 |
| 227 if (temp_map == MAP_FAILED) { |
| 228 LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf handle."; |
| 229 return false; |
| 230 } |
| 231 |
| 232 if (munmap(temp_map, stride) == -1) { |
| 233 LOG(ERROR) << "DRIBufferManager: Cannot munmap dma_buf handle."; |
| 234 return false; |
| 235 } |
| 236 |
| 237 return true; |
| 238 } |
| 239 |
| 240 } // namespace content |
| OLD | NEW |