+++ /dev/null
-/*
- * Copyright © 2008 Jérôme Glisse
- * 2009 Corbin Simpson
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
- * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- */
-/*
- * Authors:
- * Jérôme Glisse <glisse@freedesktop.org>
- * Corbin Simpson <MostAwesomeDude@gmail.com>
- */
-
-#include "radeon_buffer.h"
-#include "radeon_drm.h"
-
-#include "util/u_format.h"
-#include "util/u_math.h"
-#include "util/u_memory.h"
-
-#include "radeon_bo_gem.h"
-#include <X11/Xutil.h>
-
-struct radeon_vl_context
-{
- Display *display;
- int screen;
- Drawable drawable;
-};
-
-static const char *radeon_get_name(struct pipe_winsys *ws)
-{
- return "Radeon/GEM+KMS";
-}
-
-static uint32_t radeon_domain_from_usage(unsigned usage)
-{
- uint32_t domain = 0;
-
- if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
- domain |= RADEON_GEM_DOMAIN_VRAM;
- }
- if (usage & PIPE_BUFFER_USAGE_PIXEL) {
- domain |= RADEON_GEM_DOMAIN_VRAM;
- }
- if (usage & PIPE_BUFFER_USAGE_VERTEX) {
- domain |= RADEON_GEM_DOMAIN_GTT;
- }
- if (usage & PIPE_BUFFER_USAGE_INDEX) {
- domain |= RADEON_GEM_DOMAIN_GTT;
- }
-
- return domain;
-}
-
-static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws,
- unsigned alignment,
- unsigned usage,
- unsigned size)
-{
- struct radeon_winsys *radeon_ws = (struct radeon_winsys *)ws;
- struct radeon_pipe_buffer *radeon_buffer;
- struct pb_desc desc;
- uint32_t domain;
-
- radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer);
- if (radeon_buffer == NULL) {
- return NULL;
- }
-
- pipe_reference_init(&radeon_buffer->base.reference, 1);
- radeon_buffer->base.alignment = alignment;
- radeon_buffer->base.usage = usage;
- radeon_buffer->base.size = size;
-
- if (usage & PIPE_BUFFER_USAGE_CONSTANT && is_r3xx(radeon_ws->pci_id)) {
- /* Don't bother allocating a BO, as it'll never get to the card. */
- desc.alignment = alignment;
- desc.usage = usage;
- radeon_buffer->pb = pb_malloc_buffer_create(size, &desc);
- return &radeon_buffer->base;
- }
-
- domain = radeon_domain_from_usage(usage);
-
- radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size,
- alignment, domain, 0);
- if (radeon_buffer->bo == NULL) {
- FREE(radeon_buffer);
- return NULL;
- }
- return &radeon_buffer->base;
-}
-
-static struct pipe_buffer *radeon_buffer_user_create(struct pipe_winsys *ws,
- void *ptr,
- unsigned bytes)
-{
- struct radeon_pipe_buffer *radeon_buffer;
-
- radeon_buffer =
- (struct radeon_pipe_buffer*)radeon_buffer_create(ws, 0, 0, bytes);
- if (radeon_buffer == NULL) {
- return NULL;
- }
- radeon_bo_map(radeon_buffer->bo, 1);
- memcpy(radeon_buffer->bo->ptr, ptr, bytes);
- radeon_bo_unmap(radeon_buffer->bo);
- return &radeon_buffer->base;
-}
-
-static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws,
- unsigned width,
- unsigned height,
- enum pipe_format format,
- unsigned usage,
- unsigned tex_usage,
- unsigned *stride)
-{
- /* Radeons enjoy things in multiples of 32. */
- /* XXX this can be 32 when POT */
- const unsigned alignment = 64;
- unsigned nblocksy, size;
-
- nblocksy = util_format_get_nblocksy(format, height);
- *stride = align(util_format_get_stride(format, width), alignment);
- size = *stride * nblocksy;
-
- return radeon_buffer_create(ws, 64, usage, size);
-}
-
-static void radeon_buffer_del(struct pipe_buffer *buffer)
-{
- struct radeon_pipe_buffer *radeon_buffer =
- (struct radeon_pipe_buffer*)buffer;
-
- if (radeon_buffer->pb) {
- pipe_reference_init(&radeon_buffer->pb->base.reference, 0);
- pb_destroy(radeon_buffer->pb);
- }
-
- if (radeon_buffer->bo) {
- radeon_bo_unref(radeon_buffer->bo);
- }
-
- FREE(radeon_buffer);
-}
-
-static void *radeon_buffer_map(struct pipe_winsys *ws,
- struct pipe_buffer *buffer,
- unsigned flags)
-{
- struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv;
- struct radeon_pipe_buffer *radeon_buffer =
- (struct radeon_pipe_buffer*)buffer;
- int write = 0;
-
- if (radeon_buffer->pb) {
- return pb_map(radeon_buffer->pb, flags);
- }
-
- if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
- uint32_t domain;
-
- if (radeon_bo_is_busy(radeon_buffer->bo, &domain))
- return NULL;
- }
-
- if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) {
- priv->flush_cb(priv->flush_data);
- }
-
- if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) {
- write = 1;
- }
-
- if (radeon_bo_map(radeon_buffer->bo, write)) {
- return NULL;
- }
-
- return radeon_buffer->bo->ptr;
-}
-
-static void radeon_buffer_unmap(struct pipe_winsys *ws,
- struct pipe_buffer *buffer)
-{
- struct radeon_pipe_buffer *radeon_buffer =
- (struct radeon_pipe_buffer*)buffer;
-
- if (radeon_buffer->pb) {
- pb_unmap(radeon_buffer->pb);
- } else {
- radeon_bo_unmap(radeon_buffer->bo);
- }
-}
-
-static boolean radeon_is_buffer_referenced(struct radeon_winsys *ws,
- struct pipe_buffer *buffer)
-{
- struct radeon_pipe_buffer *radeon_buffer =
- (struct radeon_pipe_buffer*)buffer;
- uint32_t domain;
-
- /* Referenced by CS or HW. */
- return radeon_bo_is_referenced_by_cs(radeon_buffer->bo, ws->priv->cs) ||
- radeon_bo_is_busy(radeon_buffer->bo, &domain);
-}
-
-static void radeon_buffer_set_tiling(struct radeon_winsys *ws,
- struct pipe_buffer *buffer,
- uint32_t pitch,
- boolean microtiled,
- boolean macrotiled)
-{
- struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv;
- struct radeon_pipe_buffer *radeon_buffer =
- (struct radeon_pipe_buffer*)buffer;
- uint32_t flags = 0, old_flags, old_pitch;
-
- if (microtiled) {
- flags |= RADEON_BO_FLAGS_MICRO_TILE;
- }
- if (macrotiled) {
- flags |= RADEON_BO_FLAGS_MACRO_TILE;
- }
-
- radeon_bo_get_tiling(radeon_buffer->bo, &old_flags, &old_pitch);
-
- if (flags != old_flags || pitch != old_pitch) {
- /* Tiling determines how DRM treats the buffer data.
- * We must flush CS when changing it if the buffer is referenced. */
- if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) {
- priv->flush_cb(priv->flush_data);
- }
-
- radeon_bo_set_tiling(radeon_buffer->bo, flags, pitch);
- }
-}
-
-static void radeon_fence_reference(struct pipe_winsys *ws,
- struct pipe_fence_handle **ptr,
- struct pipe_fence_handle *pfence)
-{
-}
-
-static int radeon_fence_signalled(struct pipe_winsys *ws,
- struct pipe_fence_handle *pfence,
- unsigned flag)
-{
- return 1;
-}
-
-static int radeon_fence_finish(struct pipe_winsys *ws,
- struct pipe_fence_handle *pfence,
- unsigned flag)
-{
- return 0;
-}
-
-/* Create a buffer from a handle. */
-static struct pipe_buffer* radeon_buffer_from_handle(struct radeon_winsys *radeon_ws,
- struct pipe_screen *screen,
- struct winsys_handle *whandle,
- unsigned *stride)
-{
- struct radeon_bo_manager* bom = radeon_ws->priv->bom;
- struct radeon_pipe_buffer* radeon_buffer;
- struct radeon_bo* bo = NULL;
-
- bo = radeon_bo_open(bom, whandle->handle, 0, 0, 0, 0);
- if (bo == NULL) {
- return NULL;
- }
-
- radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer);
- if (radeon_buffer == NULL) {
- radeon_bo_unref(bo);
- return NULL;
- }
-
- pipe_reference_init(&radeon_buffer->base.reference, 1);
- radeon_buffer->base.screen = screen;
- radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL;
- radeon_buffer->bo = bo;
-
- *stride = whandle->stride;
-
- return &radeon_buffer->base;
-}
-
-static boolean radeon_buffer_get_handle(struct radeon_winsys *radeon_ws,
- struct pipe_buffer *buffer,
- unsigned stride,
- struct winsys_handle *whandle)
-{
- int retval, fd;
- struct drm_gem_flink flink;
- struct radeon_pipe_buffer* radeon_buffer;
-
- radeon_buffer = (struct radeon_pipe_buffer*)buffer;
-
-
- if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
- if (!radeon_buffer->flinked) {
- fd = radeon_ws->priv->fd;
-
- flink.handle = radeon_buffer->bo->handle;
-
- retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
- if (retval) {
- debug_printf("radeon: DRM_IOCTL_GEM_FLINK failed, error %d\n",
- retval);
- return FALSE;
- }
-
- radeon_buffer->flink = flink.name;
- radeon_buffer->flinked = TRUE;
- }
-
- whandle->handle = radeon_buffer->flink;
- } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
- whandle->handle = ((struct radeon_pipe_buffer*)buffer)->bo->handle;
- }
- whandle->stride = stride;
-
- return TRUE;
-}
-
-struct radeon_winsys* radeon_pipe_winsys(int fd)
-{
- struct radeon_winsys* radeon_ws;
-
- radeon_ws = CALLOC_STRUCT(radeon_winsys);
- if (radeon_ws == NULL) {
- return NULL;
- }
-
- radeon_ws->priv = CALLOC_STRUCT(radeon_winsys_priv);
- if (radeon_ws->priv == NULL) {
- FREE(radeon_ws);
- return NULL;
- }
-
- radeon_ws->priv->fd = fd;
- radeon_ws->priv->bom = radeon_bo_manager_gem_ctor(fd);
-
- radeon_ws->base.flush_frontbuffer = NULL; /* overriden by co-state tracker */
-
- radeon_ws->base.buffer_create = radeon_buffer_create;
- radeon_ws->base.user_buffer_create = radeon_buffer_user_create;
- radeon_ws->base.surface_buffer_create = radeon_surface_buffer_create;
- radeon_ws->base.buffer_map = radeon_buffer_map;
- radeon_ws->base.buffer_unmap = radeon_buffer_unmap;
- radeon_ws->base.buffer_destroy = radeon_buffer_del;
-
- radeon_ws->base.fence_reference = radeon_fence_reference;
- radeon_ws->base.fence_signalled = radeon_fence_signalled;
- radeon_ws->base.fence_finish = radeon_fence_finish;
-
- radeon_ws->base.get_name = radeon_get_name;
-
- radeon_ws->buffer_set_tiling = radeon_buffer_set_tiling;
- radeon_ws->buffer_from_handle = radeon_buffer_from_handle;
- radeon_ws->buffer_get_handle = radeon_buffer_get_handle;
-
- radeon_ws->is_buffer_referenced = radeon_is_buffer_referenced;
-
- return radeon_ws;
-}