summaryrefslogtreecommitdiff
path: root/src/gralloc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gralloc')
-rw-r--r--src/gralloc/Android.mk71
-rw-r--r--src/gralloc/gralloc_gem.c67
-rw-r--r--src/gralloc/gralloc_gem.h52
-rw-r--r--src/gralloc/gralloc_gem_intel.c (renamed from src/gralloc/gralloc_gem_i915.c)52
-rw-r--r--src/gralloc/gralloc_gem_pipe.c54
-rw-r--r--src/gralloc/gralloc_gem_radeon.c362
-rw-r--r--src/gralloc/gralloc_kms.c38
-rw-r--r--src/gralloc/gralloc_mod.c10
-rw-r--r--src/gralloc/gralloc_mod.h3
9 files changed, 594 insertions, 115 deletions
diff --git a/src/gralloc/Android.mk b/src/gralloc/Android.mk
index 4125548735..d440a99308 100644
--- a/src/gralloc/Android.mk
+++ b/src/gralloc/Android.mk
@@ -1,54 +1,47 @@
+# Android.mk for gralloc
+
LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
-common_SRC_FILES := \
+LOCAL_SRC_FILES := \
gralloc_gem.c \
gralloc_kms.c \
gralloc_mod.c
-common_C_INCLUDES := \
+LOCAL_C_INCLUDES := \
external/drm \
external/drm/include/drm
-common_SHARED_LIBRARIES := \
+LOCAL_SHARED_LIBRARIES := \
libdrm \
liblog \
- libcutils
-
-ifeq ($(strip $(MESA_BUILD_I915)),true)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(common_SRC_FILES) \
- gralloc_gem_i915.c
-
-LOCAL_C_INCLUDES := \
- $(common_C_INCLUDES) \
- external/drm/intel
-
-LOCAL_SHARED_LIBRARIES := \
- $(common_SHARED_LIBRARIES) \
- libdrm_intel \
- libEGL
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_MODULE := gralloc.i915
-
-include $(BUILD_SHARED_LIBRARY)
-endif # MESA_BUILD_I915
-
-ifeq ($(strip $(MESA_BUILD_GALLIUM)),true)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(common_SRC_FILES) \
- gralloc_gem_pipe.c
-
-LOCAL_C_INCLUDES := \
- $(common_C_INCLUDES) \
+ libcutils \
+ libGLESv1_CM
+
+ifeq ($(strip $(MESA_BUILD_INTEL)),true)
+LOCAL_SRC_FILES += gralloc_gem_intel.c
+LOCAL_C_INCLUDES += external/drm/intel
+LOCAL_CFLAGS += -DENABLE_INTEL
+LOCAL_SHARED_LIBRARIES += libdrm_intel
+endif # MESA_BUILD_INTEL
+
+ifeq ($(strip $(MESA_BUILD_RADEON)),true)
+LOCAL_SRC_FILES += gralloc_gem_radeon.c
+LOCAL_C_INCLUDES += external/drm/radeon
+LOCAL_CFLAGS += -DENABLE_RADEON
+LOCAL_SHARED_LIBRARIES += libdrm_radeon
+endif # MESA_BUILD_INTEL
+
+# this is broken
+ifeq ($(strip $(MESA_BUILD_VMWGFX)),true)
+LOCAL_SRC_FILES += gralloc_gem_pipe.c
+LOCAL_C_INCLUDES += \
external/mesa/src/gallium/include \
external/mesa/src/gallium/auxiliary
+LOCAL_CFLAGS += -DENABLE_VMWGFX
+endif # MESA_BUILD_VMWGFX
-LOCAL_MODULE := libmesa_st_gralloc
+LOCAL_MODULE := gralloc.mesa
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-include $(BUILD_STATIC_LIBRARY)
-endif # MESA_BUILD_GALLIUM
+include $(BUILD_SHARED_LIBRARY)
diff --git a/src/gralloc/gralloc_gem.c b/src/gralloc/gralloc_gem.c
index a3df97f89b..be1a77c60b 100644
--- a/src/gralloc/gralloc_gem.c
+++ b/src/gralloc/gralloc_gem.c
@@ -117,3 +117,70 @@ drm_gem_validate(buffer_handle_t handle)
return bo;
}
+
+static const struct drm_gem_drv *
+get_drv_from_fd(int fd)
+{
+ const struct drm_gem_drv *drv = NULL;
+ drmVersionPtr version;
+
+ version = drmGetVersion(fd);
+ if (!version) {
+ LOGE("invalid DRM fd");
+ return NULL;
+ }
+
+ if (version->name) {
+#ifdef ENABLE_INTEL
+ if (!drv && !strcmp(version->name, "i915"))
+ drv = &drm_gem_drv_intel;
+#endif
+#ifdef ENABLE_RADEON
+ if (!drv && !strcmp(version->name, "radeon"))
+ drv = &drm_gem_drv_radeon;
+#endif
+#ifdef ENABLE_VMWGFX
+ if (!drv && !strcmp(version->name, "vmwgfx"))
+ drv = &drm_gem_drv_pipe;
+#endif
+ }
+
+ if (!drv)
+ LOGE("unknown driver: %s", (version->name) ? version->name : "NULL");
+
+ drmFreeVersion(version);
+
+ return drv;
+}
+
+static int
+drm_gem_drv_init_locked(struct drm_module_t *drm)
+{
+ const struct drm_gem_drv *drv;
+ int ret;
+
+ if (drm->gem)
+ return 0;
+
+ drv = get_drv_from_fd(drm->fd);
+ if (!drv)
+ return -EINVAL;
+
+ ret = drv->init(drm);
+ if (!ret)
+ drm->drv = (void *) drv;
+
+ return ret;
+}
+
+int
+drm_gem_drv_init(struct drm_module_t *drm)
+{
+ int ret;
+
+ pthread_mutex_lock(&drm->mutex);
+ ret = drm_gem_drv_init_locked(drm);
+ pthread_mutex_unlock(&drm->mutex);
+
+ return ret;
+}
diff --git a/src/gralloc/gralloc_gem.h b/src/gralloc/gralloc_gem.h
index e6ef176efa..f8fa1e069d 100644
--- a/src/gralloc/gralloc_gem.h
+++ b/src/gralloc/gralloc_gem.h
@@ -56,22 +56,56 @@ drm_gem_validate(buffer_handle_t handle);
struct drm_bo_t *
drm_gem_create_bo(int width, int height, int format, int usage);
-
int
drm_gem_drv_init(struct drm_module_t *drm);
-struct drm_bo_t *
+
+struct drm_gem_drv {
+ int (*init)(struct drm_module_t *drm);
+
+ struct drm_bo_t *(*alloc)(struct drm_module_t *drm, int width, int height,
+ int format, int usage, int *stride);
+
+ void (*free)(struct drm_module_t *drm, struct drm_bo_t *bo);
+
+ int (*map)(struct drm_module_t *drm, struct drm_bo_t *bo,
+ int x, int y, int w, int h, int enable_write, void **addr);
+
+ void (*unmap)(struct drm_module_t *drm, struct drm_bo_t *bo);
+};
+
+extern const struct drm_gem_drv drm_gem_drv_intel;
+extern const struct drm_gem_drv drm_gem_drv_radeon;
+extern const struct drm_gem_drv drm_gem_drv_pipe;
+
+static inline struct drm_bo_t *
drm_gem_drv_alloc(struct drm_module_t *drm, int width, int height,
- int format, int usage, int *stride);
+ int format, int usage, int *stride)
+{
+ const struct drm_gem_drv *drv = (const struct drm_gem_drv *) drm->drv;
+ return drv->alloc(drm, width, height, format, usage, stride);
+}
-void
-drm_gem_drv_free(struct drm_module_t *drm, struct drm_bo_t *bo);
+static inline void
+drm_gem_drv_free(struct drm_module_t *drm, struct drm_bo_t *bo)
+{
+ const struct drm_gem_drv *drv = (const struct drm_gem_drv *) drm->drv;
+ drv->free(drm, bo);
+}
-int
+static inline int
drm_gem_drv_map(struct drm_module_t *drm, struct drm_bo_t *bo,
- int x, int y, int w, int h, int enable_write, void **addr);
+ int x, int y, int w, int h, int enable_write, void **addr)
+{
+ const struct drm_gem_drv *drv = (const struct drm_gem_drv *) drm->drv;
+ return drv->map(drm, bo, x, y, w, h, enable_write, addr);
+}
-void
-drm_gem_drv_unmap(struct drm_module_t *drm, struct drm_bo_t *bo);
+static inline void
+drm_gem_drv_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
+{
+ const struct drm_gem_drv *drv = (const struct drm_gem_drv *) drm->drv;
+ drv->unmap(drm, bo);
+}
#endif /* _GRALLOC_GEM_H_ */
diff --git a/src/gralloc/gralloc_gem_i915.c b/src/gralloc/gralloc_gem_intel.c
index 2822fe5c12..5cd765b562 100644
--- a/src/gralloc/gralloc_gem_i915.c
+++ b/src/gralloc/gralloc_gem_intel.c
@@ -11,7 +11,7 @@
#include "gralloc_gem.h"
static void
-drm_gem_drv_init_features_locked(struct drm_module_t *drm)
+drm_gem_intel_init_features(struct drm_module_t *drm)
{
struct drm_i915_getparam gp;
@@ -27,6 +27,8 @@ drm_gem_drv_init_features_locked(struct drm_module_t *drm)
else
drm->mode_page_flip = 0;
+ drm->mode_page_flip_blocking = 0;
+
if (drm->resources) {
int pipe;
@@ -40,38 +42,22 @@ drm_gem_drv_init_features_locked(struct drm_module_t *drm)
/* XXX there is a bug in the kernel module */
drm->mode_page_flip = 0;
-
}
static int
-drm_gem_drv_init_locked(struct drm_module_t *drm)
+drm_gem_intel_init(struct drm_module_t *drm)
{
- if (drm->gem)
- return 0;
-
drm->gem = (void *) drm_intel_bufmgr_gem_init(drm->fd, 16 * 1024);
if (!drm->gem) {
LOGE("failed to create buffer manager");
return -ENOMEM;
}
- drm_gem_drv_init_features_locked(drm);
+ drm_gem_intel_init_features(drm);
return 0;
}
-int
-drm_gem_drv_init(struct drm_module_t *drm)
-{
- int ret;
-
- pthread_mutex_lock(&drm->mutex);
- ret = drm_gem_drv_init_locked(drm);
- pthread_mutex_unlock(&drm->mutex);
-
- return ret;
-}
-
static uint32_t
drm_gem_get_tiling(struct drm_bo_t *bo)
{
@@ -89,9 +75,9 @@ drm_gem_get_tiling(struct drm_bo_t *bo)
return tiling;
}
-struct drm_bo_t *
-drm_gem_drv_alloc(struct drm_module_t *drm, int width, int height,
- int format, int usage, int *stride)
+static struct drm_bo_t *
+drm_gem_intel_alloc(struct drm_module_t *drm, int width, int height,
+ int format, int usage, int *stride)
{
drm_intel_bufmgr *bufmgr = (drm_intel_bufmgr *) drm->gem;
struct drm_bo_t *bo;
@@ -161,16 +147,16 @@ drm_gem_drv_alloc(struct drm_module_t *drm, int width, int height,
return bo;
}
-void
-drm_gem_drv_free(struct drm_module_t *drm, struct drm_bo_t *bo)
+static void
+drm_gem_intel_free(struct drm_module_t *drm, struct drm_bo_t *bo)
{
drm_intel_bo_unreference((drm_intel_bo *) bo->data);
free(bo);
}
-int
-drm_gem_drv_map(struct drm_module_t *drm, struct drm_bo_t *bo,
- int x, int y, int w, int h, int enable_write, void **addr)
+static int
+drm_gem_intel_map(struct drm_module_t *drm, struct drm_bo_t *bo,
+ int x, int y, int w, int h, int enable_write, void **addr)
{
drm_intel_bo *ibo = (drm_intel_bo *) bo->data;
int err;
@@ -198,8 +184,8 @@ drm_gem_drv_map(struct drm_module_t *drm, struct drm_bo_t *bo,
return err;
}
-void
-drm_gem_drv_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
+static void
+drm_gem_intel_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
{
drm_intel_bo *ibo = (drm_intel_bo *) bo->data;
@@ -209,3 +195,11 @@ drm_gem_drv_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
else
drm_intel_bo_unmap(ibo);
}
+
+const struct drm_gem_drv drm_gem_drv_intel = {
+ .init = drm_gem_intel_init,
+ .alloc = drm_gem_intel_alloc,
+ .free = drm_gem_intel_free,
+ .map = drm_gem_intel_map,
+ .unmap = drm_gem_intel_unmap,
+};
diff --git a/src/gralloc/gralloc_gem_pipe.c b/src/gralloc/gralloc_gem_pipe.c
index 99a8461627..74b35d0537 100644
--- a/src/gralloc/gralloc_gem_pipe.c
+++ b/src/gralloc/gralloc_gem_pipe.c
@@ -26,10 +26,11 @@ struct drm_pipe_buffer {
};
static void
-drm_gem_drv_init_features_locked(struct drm_module_t *drm)
+drm_gem_pipe_init_features(struct drm_module_t *drm)
{
drm->mode_dirty_fb = 0;
drm->mode_page_flip = 0;
+ drm->mode_page_flip_blocking = 0;
if (strcmp(driver_descriptor.driver_name, "vmwgfx") == 0)
drm->mode_dirty_fb = 1;
@@ -38,13 +39,10 @@ drm_gem_drv_init_features_locked(struct drm_module_t *drm)
}
static int
-drm_gem_drv_init_locked(struct drm_module_t *drm)
+drm_gem_pipe_init(struct drm_module_t *drm)
{
struct drm_pipe_manager *pm;
- if (drm->gem)
- return 0;
-
pm = CALLOC(1, sizeof(*pm));
if (!pm)
return -ENOMEM;
@@ -60,23 +58,11 @@ drm_gem_drv_init_locked(struct drm_module_t *drm)
drm->gem = (void *) pm;
- drm_gem_drv_init_features_locked(drm);
+ drm_gem_pipe_init_features(drm);
return 0;
}
-int
-drm_gem_drv_init(struct drm_module_t *drm)
-{
- int ret;
-
- pthread_mutex_lock(&drm->mutex);
- ret = drm_gem_drv_init_locked(drm);
- pthread_mutex_unlock(&drm->mutex);
-
- return ret;
-}
-
static enum pipe_format
get_pipe_format(int format)
{
@@ -144,7 +130,7 @@ get_pipe_buffer(struct drm_pipe_manager *pm, int width, int height,
if (templ.format == PIPE_FORMAT_NONE ||
!pm->screen->is_format_supported(pm->screen, templ.format,
- templ.target, 0, templ.bind, 0)) {
+ templ.target, 0, templ.bind)) {
LOGE("unsupported format 0x%x", format);
return NULL;
}
@@ -198,9 +184,9 @@ fail:
return NULL;
}
-struct drm_bo_t *
-drm_gem_drv_alloc(struct drm_module_t *drm, int width, int height,
- int format, int usage, int *stride)
+static struct drm_bo_t *
+drm_gem_pipe_alloc(struct drm_module_t *drm, int width, int height,
+ int format, int usage, int *stride)
{
struct drm_pipe_manager *pm = (struct drm_pipe_manager *) drm->gem;
struct drm_pipe_buffer *buf;
@@ -232,8 +218,8 @@ drm_gem_drv_alloc(struct drm_module_t *drm, int width, int height,
return bo;
}
-void
-drm_gem_drv_free(struct drm_module_t *drm, struct drm_bo_t *bo)
+static void
+drm_gem_pipe_free(struct drm_module_t *drm, struct drm_bo_t *bo)
{
struct drm_pipe_manager *pm = (struct drm_pipe_manager *) drm->gem;
struct drm_pipe_buffer *buf = (struct drm_pipe_buffer *) bo->data;
@@ -250,9 +236,9 @@ drm_gem_drv_free(struct drm_module_t *drm, struct drm_bo_t *bo)
free(bo);
}
-int
-drm_gem_drv_map(struct drm_module_t *drm, struct drm_bo_t *bo,
- int x, int y, int w, int h, int enable_write, void **addr)
+static int
+drm_gem_pipe_map(struct drm_module_t *drm, struct drm_bo_t *bo,
+ int x, int y, int w, int h, int enable_write, void **addr)
{
struct drm_pipe_manager *pm = (struct drm_pipe_manager *) drm->gem;
struct drm_pipe_buffer *buf = (struct drm_pipe_buffer *) bo->data;
@@ -313,8 +299,8 @@ drm_gem_drv_map(struct drm_module_t *drm, struct drm_bo_t *bo,
return ret;
}
-void
-drm_gem_drv_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
+static void
+drm_gem_pipe_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
{
struct drm_pipe_manager *pm = (struct drm_pipe_manager *) drm->gem;
struct drm_pipe_buffer *buf = (struct drm_pipe_buffer *) bo->data;
@@ -327,7 +313,15 @@ drm_gem_drv_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
pipe_transfer_destroy(pm->context, buf->transfer);
buf->transfer = NULL;
- pm->context->flush(pm->context, PIPE_FLUSH_RENDER_CACHE, NULL);
+ pm->context->flush(pm->context, NULL);
pthread_mutex_unlock(&pm->mutex);
}
+
+const struct drm_gem_drv drm_gem_drv_pipe = {
+ .init = drm_gem_pipe_init,
+ .alloc = drm_gem_pipe_alloc,
+ .free = drm_gem_pipe_free,
+ .map = drm_gem_pipe_map,
+ .unmap = drm_gem_pipe_unmap,
+};
diff --git a/src/gralloc/gralloc_gem_radeon.c b/src/gralloc/gralloc_gem_radeon.c
new file mode 100644
index 0000000000..469a1488a0
--- /dev/null
+++ b/src/gralloc/gralloc_gem_radeon.c
@@ -0,0 +1,362 @@
+/*
+ * Based on xf86-video-ati, which is
+ *
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * 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, sublicense,
+ * 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 above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ */
+
+/*
+ * XXX This driver assumes evergreen. It works, but is slow and has sync
+ * issues.
+ */
+
+#define LOG_TAG "GRALLOC-RADEON"
+
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <drm.h>
+#include <radeon_drm.h>
+#include <radeon_bo_gem.h>
+#include <radeon_bo.h>
+
+#include "gralloc_mod.h"
+#include "gralloc_gem.h"
+
+#define RADEON_GPU_PAGE_SIZE 4096
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
+
+struct radeon_info {
+ struct drm_module_t *drm;
+ struct radeon_bo_manager *bufmgr;
+
+ uint32_t tile_config;
+ int num_channels;
+ int num_banks;
+ int group_bytes;
+ /* r6xx+ tile config */
+ int have_tiling_info;
+ int allow_color_tiling;
+};
+
+static int
+eg_init_tile_config(struct radeon_info *info)
+{
+ struct drm_radeon_info ginfo;
+ uint32_t val;
+ int ret;
+
+ memset(&ginfo, 0, sizeof(ginfo));
+ ginfo.request = RADEON_INFO_TILING_CONFIG;
+ ginfo.value = (long) &val;
+ ret = drmCommandWriteRead(info->drm->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
+ if (ret)
+ return ret;
+
+ info->tile_config = val;
+
+ switch (info->tile_config & 0xf) {
+ case 0:
+ info->num_channels = 1;
+ break;
+ case 1:
+ info->num_channels = 2;
+ break;
+ case 2:
+ info->num_channels = 4;
+ break;
+ case 3:
+ info->num_channels = 8;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ info->num_banks = (info->tile_config & 0xf0) >> 4;
+
+ switch ((info->tile_config & 0xf00) >> 8) {
+ case 0:
+ info->group_bytes = 256;
+ break;
+ case 1:
+ info->group_bytes = 512;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ info->have_tiling_info = 1;
+ info->allow_color_tiling = 0;
+
+ return 0;
+}
+
+/* returns pitch alignment in pixels */
+static int
+eg_get_pitch_align(struct radeon_info *info, int bpe, uint32_t tiling)
+{
+ int pitch_align = 1;
+
+ if (tiling & RADEON_TILING_MACRO) {
+ /* general surface requirements */
+ pitch_align = MAX(info->num_banks,
+ (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8;
+ /* further restrictions for scanout */
+ pitch_align = MAX(info->num_banks * 8, pitch_align);
+ } else if (tiling & RADEON_TILING_MICRO) {
+ /* general surface requirements */
+ pitch_align = MAX(8, (info->group_bytes / (8 * bpe)));
+ /* further restrictions for scanout */
+ pitch_align = MAX(info->group_bytes / bpe, pitch_align);
+ } else {
+ if (info->have_tiling_info)
+ /* linear aligned requirements */
+ pitch_align = MAX(64, info->group_bytes / bpe);
+ else
+ /* default to 512 elements if we don't know the real
+ * group size otherwise the kernel may reject the CS
+ * if the group sizes don't match as the pitch won't
+ * be aligned properly.
+ */
+ pitch_align = 512;
+ }
+
+ return pitch_align;
+}
+
+/* returns height alignment in pixels */
+static int
+eg_get_height_align(struct radeon_info *info, uint32_t tiling)
+{
+ int height_align = 1;
+
+ if (tiling & RADEON_TILING_MACRO)
+ height_align = info->num_channels * 8;
+ else if (tiling & RADEON_TILING_MICRO)
+ height_align = 8;
+ else
+ height_align = 8;
+
+ return height_align;
+}
+
+/* returns base alignment in bytes */
+static int
+eg_get_base_align(struct radeon_info *info, int bpe, uint32_t tiling)
+{
+ int pixel_align = eg_get_pitch_align(info, bpe, tiling);
+ int height_align = eg_get_height_align(info, tiling);
+ int base_align = RADEON_GPU_PAGE_SIZE;
+
+ if (tiling & RADEON_TILING_MACRO) {
+ base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe,
+ pixel_align * bpe * height_align);
+ }
+ else {
+ if (info->have_tiling_info)
+ base_align = info->group_bytes;
+ else
+ /* default to 512 if we don't know the real
+ * group size otherwise the kernel may reject the CS
+ * if the group sizes don't match as the base won't
+ * be aligned properly.
+ */
+ base_align = 512;
+ }
+
+ return base_align;
+}
+
+static void
+drm_gem_radeon_init_features(struct drm_module_t *drm)
+{
+ drm->mode_dirty_fb = 0;
+ drm->mode_page_flip = 1;
+ drm->mode_page_flip_blocking = 1;
+ drm->swap_interval = 1;
+ drm->vblank_secondary = 0;
+}
+
+static int
+drm_gem_radeon_init(struct drm_module_t *drm)
+{
+ struct radeon_info *info;
+ int ret;
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return -ENOMEM;
+
+ info->drm = drm;
+ info->bufmgr = radeon_bo_manager_gem_ctor(info->drm->fd);
+ if (!info->bufmgr) {
+ LOGE("failed to create buffer manager");
+ free(info);
+ return -ENOMEM;
+ }
+
+
+ drm->gem = (void *) info;
+
+ ret = eg_init_tile_config(info);
+ if (ret) {
+ radeon_bo_manager_gem_dtor(info->bufmgr);
+ free(info);
+ return ret;
+ }
+
+ drm_gem_radeon_init_features(drm);
+
+ return 0;
+}
+
+static uint32_t
+drm_gem_get_tiling(struct drm_bo_t *bo)
+{
+ return 0;
+}
+
+static struct drm_bo_t *
+drm_gem_radeon_alloc(struct drm_module_t *drm, int width, int height,
+ int format, int usage, int *stride)
+{
+ struct radeon_info *info = (struct radeon_info *) drm->gem;
+ struct drm_bo_t *bo;
+ struct radeon_bo *rbo;
+ int aligned_width, aligned_height, cpp;
+ int pitch, size, base_align;
+ uint32_t tiling, domain;
+
+ bo = drm_gem_create_bo(width, height, format, usage);
+ if (!bo)
+ return NULL;
+
+ cpp = drm_mod_get_bpp(format);
+ if (!cpp) {
+ LOGE("unrecognized format 0x%x", format);
+ free(bo);
+ return NULL;
+ }
+
+ tiling = drm_gem_get_tiling(bo);
+ domain = RADEON_GEM_DOMAIN_VRAM;
+
+ if (usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_TEXTURE)) {
+ aligned_width = ALIGN(width, eg_get_pitch_align(info, cpp, tiling));
+ aligned_height = ALIGN(height, eg_get_height_align(info, tiling));
+ }
+ else {
+ aligned_width = width;
+ aligned_height = height;
+ }
+
+ if (!(usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER)) &&
+ (usage & GRALLOC_USAGE_SW_READ_OFTEN))
+ domain = RADEON_GEM_DOMAIN_GTT;
+
+ pitch = aligned_width * cpp;
+ size = ALIGN(aligned_height * pitch, RADEON_GPU_PAGE_SIZE);
+ base_align = eg_get_base_align(info, cpp, tiling);
+
+ rbo = radeon_bo_open(info->bufmgr, 0, size, base_align, domain, 0);
+ if (!rbo) {
+ LOGE("failed to allocate rbo %dx%dx%d", width, height, cpp);
+ free(bo);
+ return NULL;
+ }
+
+ if (tiling)
+ radeon_bo_set_tiling(rbo, tiling, pitch);
+
+ if (bo->usage & GRALLOC_USAGE_HW_FB) {
+ bo->stride = pitch;
+ bo->fb_handle = rbo->handle;
+ }
+
+ if (radeon_gem_get_kernel_name(rbo, (uint32_t *) &bo->name)) {
+ LOGE("failed to flink rbo");
+ radeon_bo_unref(rbo);
+ free(bo);
+ return NULL;
+ }
+
+ bo->data = (int) rbo;
+
+ *stride = pitch;
+
+ return bo;
+}
+
+static void
+drm_gem_radeon_free(struct drm_module_t *drm, struct drm_bo_t *bo)
+{
+ radeon_bo_unref((struct radeon_bo *) bo->data);
+ free(bo);
+}
+
+static int
+drm_gem_radeon_map(struct drm_module_t *drm, struct drm_bo_t *bo,
+ int x, int y, int w, int h, int enable_write, void **addr)
+{
+ struct radeon_bo *rbo = (struct radeon_bo *) bo->data;
+ int err;
+
+ if (!rbo) {
+ struct radeon_info *info = (struct radeon_info *) drm->gem;
+
+ rbo = radeon_bo_open(info->bufmgr, bo->name, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ if (!rbo) {
+ LOGE("failed to create rbo from name %u", bo->name);
+ return -EINVAL;
+ }
+
+ bo->data = (int) rbo;
+ }
+
+ err = radeon_bo_map(rbo, enable_write);
+ if (!err)
+ *addr = rbo->ptr;
+
+ return err;
+}
+
+static void
+drm_gem_radeon_unmap(struct drm_module_t *drm, struct drm_bo_t *bo)
+{
+ struct radeon_bo *rbo = (struct radeon_bo *) bo->data;
+
+ radeon_bo_unmap(rbo);
+}
+
+const struct drm_gem_drv drm_gem_drv_radeon = {
+ .init = drm_gem_radeon_init,
+ .alloc = drm_gem_radeon_alloc,
+ .free = drm_gem_radeon_free,
+ .map = drm_gem_radeon_map,
+ .unmap = drm_gem_radeon_unmap,
+};
diff --git a/src/gralloc/gralloc_kms.c b/src/gralloc/gralloc_kms.c
index 6ae9446244..7bc65b3438 100644
--- a/src/gralloc/gralloc_kms.c
+++ b/src/gralloc/gralloc_kms.c
@@ -63,28 +63,52 @@ drm_kms_set_crtc(struct drm_module_t *drm, struct drm_bo_t *bo)
return ret;
}
+static void page_flip_handler(int fd, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data)
+{
+ struct drm_module_t *drm = (struct drm_module_t *) user_data;
+
+ drm->flip_pending = 0;
+}
+
static int
drm_kms_page_flip(struct drm_module_t *drm, struct drm_bo_t *bo)
{
- int waits = 3, ret;
+ int retries = 3, ret;
if (drm->swap_interval > 1)
drm_kms_wait_vblank(drm, drm->swap_interval - 1);
- while (waits) {
- ret = drmModePageFlip(drm->fd, drm->crtc_id, bo->fb_id, 0x0, NULL);
- if (ret && errno == -EBUSY) {
+ /* TODO throttle page flip instead of retrying here */
+ while (retries) {
+ ret = drmModePageFlip(drm->fd, drm->crtc_id, bo->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, (void *) drm);
+ if (ret && errno == EBUSY) {
if (drm->swap_interval)
drm_kms_wait_vblank(drm, 1);
else
usleep(5000);
- waits--;
+ retries--;
}
else {
+ if (!ret)
+ drm->flip_pending = 1;
break;
}
}
+ if (drm->mode_page_flip_blocking && drm->flip_pending) {
+ drmEventContext ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.version = DRM_EVENT_CONTEXT_VERSION;
+ ctx.page_flip_handler = page_flip_handler;
+
+ while (drm->flip_pending)
+ drmHandleEvent(drm->fd, &ctx);
+ }
+
if (ret)
LOGE("failed to perform page flip");
@@ -202,8 +226,10 @@ drm_kms_init_locked(struct drm_module_t *drm)
return 0;
drm->resources = drmModeGetResources(drm->fd);
- if (!drm->resources)
+ if (!drm->resources) {
+ LOGE("failed to get modeset resources");
return -EINVAL;
+ }
for (i = 0; i < drm->resources->count_connectors; i++) {
drmModeConnectorPtr connector;
diff --git a/src/gralloc/gralloc_mod.c b/src/gralloc/gralloc_mod.c
index 1296d2af04..bc0786eb3e 100644
--- a/src/gralloc/gralloc_mod.c
+++ b/src/gralloc/gralloc_mod.c
@@ -222,11 +222,17 @@ drm_mod_post_fb0(struct framebuffer_device_t *fb, buffer_handle_t handle)
return drm_kms_post(drm, bo);
}
-#include <EGL/egl.h>
+#include <GLES/gl.h>
static int
drm_mod_composition_complete_fb0(struct framebuffer_device_t *fb)
{
- eglWaitClient();
+ struct drm_module_t *drm = (struct drm_module_t *) fb->common.module;
+
+ if (drm->mode_page_flip)
+ glFlush();
+ else
+ glFinish();
+
return 0;
}
diff --git a/src/gralloc/gralloc_mod.h b/src/gralloc/gralloc_mod.h
index e06ec864ad..33f6e9a91d 100644
--- a/src/gralloc/gralloc_mod.h
+++ b/src/gralloc/gralloc_mod.h
@@ -26,13 +26,16 @@ struct drm_module_t {
#endif
/* initialized by drm_gem_drv_init */
+ void *drv;
void *gem;
int mode_dirty_fb;
int mode_page_flip;
+ int mode_page_flip_blocking; /* page flip should block */
int swap_interval;
int vblank_secondary;
int first_post;
+ int flip_pending;
};
static inline int