| Index: content/browser/gpu/dri_buffer_manager.cc
|
| ===================================================================
|
| --- content/browser/gpu/dri_buffer_manager.cc (revision 0)
|
| +++ content/browser/gpu/dri_buffer_manager.cc (revision 0)
|
| @@ -0,0 +1,240 @@
|
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/gpu/dri_buffer_manager.h"
|
| +
|
| +extern "C" {
|
| +#include <fcntl.h>
|
| +#include </home/marius/mesa_ander/src/gbm/main/gbm.h>
|
| +#include <sys/mman.h>
|
| +#include <unistd.h>
|
| +#include <X11/Xlib.h>
|
| +#include <X11/Xlibint.h>
|
| +#include <X11/extensions/Xext.h>
|
| +#include <X11/extensions/extutil.h>
|
| +#include <X11/X.h>
|
| +#include <X11/Xproto.h>
|
| +#include <X11/extensions/dri2proto.h>
|
| +#include <xf86drm.h>
|
| +}
|
| +
|
| +#include "base/logging.h"
|
| +#include "ui/gfx/x/x11_types.h"
|
| +//#define USE_DMA_BUF_MMAP
|
| +//#define __DEBUG__
|
| +namespace content {
|
| +
|
| +const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
|
| +static char dri2ExtensionName[] = DRI2_NAME;
|
| +static XExtensionInfo *dri2Info;
|
| +static XEXT_GENERATE_CLOSE_DISPLAY(DRI2CloseDisplay, dri2Info)
|
| +static /* const */ XExtensionHooks dri2ExtensionHooks = {
|
| + NULL, // create_gc
|
| + NULL, // copy_gc
|
| + NULL, // flush_gc
|
| + NULL, // free_gc
|
| + NULL, // create_font
|
| + NULL, // free_font
|
| + DRI2CloseDisplay, // close_display
|
| + NULL, // wire_to_event
|
| + NULL, // event_to_wire
|
| + NULL, // error
|
| + NULL, // error_string
|
| +};
|
| +
|
| +static XEXT_GENERATE_FIND_DISPLAY(DRI2FindDisplay, dri2Info,
|
| + dri2ExtensionName,
|
| + &dri2ExtensionHooks,
|
| + 0,
|
| + NULL)
|
| +int DRIBufferManager::fd_ = 0;
|
| +struct gbm_device* DRIBufferManager::gbm_ = NULL;
|
| +
|
| +DRIBufferManager::DRIBufferManager() /*: fd_(0),
|
| + gbm_(NULL)*/ {
|
| + AuthConnection();
|
| +}
|
| +
|
| +DRIBufferManager::~DRIBufferManager() {
|
| + if (gbm_)
|
| + gbm_device_destroy(gbm_);
|
| + close(fd_);
|
| +}
|
| +
|
| +void DRIBufferManager::CreateBuffer(int width,
|
| + int height,
|
| + gfx::GpuMemoryBufferHandle& handle) {
|
| + //DCHECK(fd_);
|
| + if (fd_ <= 0) {
|
| + if(!AuthConnection()) {
|
| + fprintf(stderr, "\nAuthConnection failed!\n");
|
| + return;
|
| + }
|
| + fprintf(stderr, "\n CONNECTION ready!\n");
|
| + }
|
| + if (!gbm_) {
|
| + gbm_ = gbm_create_device(fd_);
|
| + //fprintf(stderr, "\nGBM CREATED %d\n", fd_);
|
| + if (!gbm_) {
|
| + LOG(ERROR) << "DRIBufferManager: Failed to create GBM device.";
|
| + return;
|
| + }
|
| + }
|
| + #if defined(USE_DMA_BUF_MMAP)
|
| + if (!IsMmapSupported()) {
|
| + fprintf(stderr, "\nMMAP Is NOT SUPPORTED!\n");
|
| + fflush(stderr);
|
| + return;
|
| + }
|
| + #endif
|
| + // TODO(kalyan): how do we free this buffer?
|
| + struct gbm_bo* tex_bo = gbm_bo_create(gbm_,
|
| + width,
|
| + height,
|
| + GBM_BO_FORMAT_ARGB8888,
|
| + GBM_BO_USE_MAP);
|
| + if (!tex_bo) {
|
| + LOG(ERROR) << "DRIBufferManager: Failed to allocate buffer.";
|
| + fprintf(stderr, "\nDRIBufferManager: Failed to allocate buffer.");
|
| + return;
|
| + }
|
| +
|
| + int dma_buf_handle;
|
| + /*
|
| + gbm_bo_export(tex_bo,
|
| + GBM_BO_IMPORT_DMA_BUF,
|
| + reinterpret_cast<void**>(&dma_buf_handle),
|
| + GBM_BO_USE_MAP);
|
| + */
|
| + dma_buf_handle = gbm_bo_get_fd(tex_bo);
|
| + handle.type = gfx::DMA_BUFFER;
|
| + handle.card_handle.fd = fd_;
|
| + handle.handle.fd = dma_buf_handle;
|
| + handle.stride = gbm_bo_get_stride(tex_bo);
|
| + DCHECK( handle.stride > width);
|
| +
|
| +#ifdef __DEBUG__
|
| + fprintf(stderr, "\nDRIBufferManager::CreateBuffer(%d,%d,%d)=%d\n", width, height, handle.stride, dma_buf_handle);
|
| + fflush(stderr);
|
| +#endif
|
| +
|
| +}
|
| +
|
| +bool DRIBufferManager::AuthConnection() {
|
| + // TODO(Kalyan): we would need to check for dri3 support when using GLX.
|
| + fd_ = open(kDefaultGraphicsCardPath, O_RDWR);
|
| + if (fd_ <= 0) {
|
| + return false;
|
| + }
|
| +
|
| + drm_magic_t magic;
|
| + if (drmGetMagic(fd_, &magic)) {
|
| + close(fd_);
|
| + return false;
|
| + }
|
| +
|
| + Display *dpy = reinterpret_cast<Display *>(gfx::GetXDisplay());
|
| + XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
| + xDRI2AuthenticateReq *req;
|
| + xDRI2AuthenticateReply rep;
|
| +
|
| + XextCheckExtension(dpy, info, dri2ExtensionName, False);
|
| + LockDisplay(dpy);
|
| + GetReq(DRI2Authenticate, req);
|
| + req->reqType = info->codes->major_opcode;
|
| + req->dri2ReqType = X_DRI2Authenticate;
|
| + req->magic = magic;
|
| + req->window = DefaultRootWindow(dpy);
|
| + if (!_XReply(dpy, reinterpret_cast<xReply *>(&rep), 0, xFalse)) {
|
| + UnlockDisplay(dpy);
|
| + SyncHandle();
|
| + return false;
|
| + }
|
| +
|
| + UnlockDisplay(dpy);
|
| + SyncHandle();
|
| +
|
| + if (!rep.authenticated) {
|
| + close(fd_);
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool DRIBufferManager::IsMmapSupported() {
|
| + static bool dma_buf_mmap_supported = true;
|
| + static bool check_done = false;
|
| + if (check_done)
|
| + return dma_buf_mmap_supported;
|
| +
|
| + fprintf(stderr, "\nCHECK!\n");
|
| + fflush(stderr);
|
| + check_done = true;
|
| + struct gbm_bo* temp_bo = gbm_bo_create(gbm_,
|
| + 1,
|
| + 1,
|
| + GBM_BO_FORMAT_ARGB8888,
|
| + GBM_BO_USE_MAP);
|
| +
|
| + int temp;
|
| + /*
|
| + gbm_bo_export(temp_bo,
|
| + GBM_BO_IMPORT_DMA_BUF,
|
| + reinterpret_cast<void**>(&temp),
|
| + GBM_BO_USE_MAP);
|
| + */
|
| + temp = gbm_bo_get_fd(temp_bo);
|
| +
|
| + int stride = gbm_bo_get_stride(temp_bo);
|
| +
|
| + // Check if platform supports mmap with proc_read.
|
| + if (!MmapDmaBuf(temp, PROT_READ, stride)) {
|
| + LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf"
|
| + << "handle with PROT_READ.";
|
| + dma_buf_mmap_supported = false;
|
| + }
|
| +
|
| + // Check if platform supports mmap with proc_write.
|
| + if (!MmapDmaBuf(temp, PROT_WRITE, stride)) {
|
| + LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf"
|
| + << "handle with PROT_WRITE.";
|
| + dma_buf_mmap_supported = false;
|
| + }
|
| +
|
| + // Check if platform supports mmap with proc_write and proc_read.
|
| +
|
| + if (!MmapDmaBuf(temp, (PROT_READ | PROT_WRITE), stride)) {
|
| + LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf"
|
| + << "handle with PROT_READ | PROT_WRITE.";
|
| + dma_buf_mmap_supported = false;
|
| + }
|
| +
|
| + gbm_bo_destroy(temp_bo);
|
| + close(temp);
|
| + return dma_buf_mmap_supported;
|
| +}
|
| +
|
| +bool DRIBufferManager::MmapDmaBuf(int dma_buf_id, int proc, int stride) {
|
| + void* temp_map = mmap(NULL,
|
| + stride,
|
| + proc,
|
| + MAP_SHARED,
|
| + dma_buf_id,
|
| + 0);
|
| +
|
| + if (temp_map == MAP_FAILED) {
|
| + LOG(ERROR) << "DRIBufferManager: Cannot mmap dma_buf handle.";
|
| + return false;
|
| + }
|
| +
|
| + if (munmap(temp_map, stride) == -1) {
|
| + LOG(ERROR) << "DRIBufferManager: Cannot munmap dma_buf handle.";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace content
|
|
|