summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/egl/drivers/android/droid_intel.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/src/egl/drivers/android/droid_intel.c b/src/egl/drivers/android/droid_intel.c
index d9ff0d59d6..4c86dcc30d 100644
--- a/src/egl/drivers/android/droid_intel.c
+++ b/src/egl/drivers/android/droid_intel.c
@@ -42,13 +42,35 @@
#include "droid.h"
#include "droid_ui.h"
+#define INTEL_IS_I965(x) ((x) & INTEL_GEN_4)
+#define INTEL_IS_I915(x) ((x) & INTEL_GEN_3)
+#define INTEL_IS_I9xx(x) ((x) & (INTEL_GEN_3 | INTEL_GEN_4))
+#define INTEL_IS_I8xx(x) ((x) & (INTEL_GEN_1 | INTEL_GEN_2))
+
#define INTEL_STRIDE_ALIGNMENT 64
+#define INTEL_HAS_128_BYTE_Y_TILING(x) \
+ (((x) & (INTEL_GEN_3 | INTEL_GEN_4 | INTEL_GEN_MINOR_MASK)) > INTEL_GEN_3)
+
enum {
INTEL_SURFACE_TYPE_WINDOW,
INTEL_SURFACE_TYPE_IMAGE,
};
+/* Look at xf86-video-intel/src/common.h for the full horror of device
+ * identification.
+ */
+enum {
+ INTEL_GEN_1 = 0x10,
+ INTEL_GEN_2 = 0x20,
+ INTEL_GEN_3 = 0x40,
+ INTEL_GEN_31 = 0x41,
+ INTEL_GEN_4 = 0x80,
+
+ INTEL_GEN_MAJOR_MASK = 0xf0,
+ INTEL_GEN_MINOR_MASK = 0x0f,
+};
+
struct droid_backend_intel {
struct droid_backend base;
int fd;
@@ -110,21 +132,90 @@ align_to(uint32_t value, uint32_t align)
return (value + align - 1) & ~(align - 1);
}
+static uint32_t
+tiling_stride(int dev, int tiling_mode, uint32_t pitch)
+{
+ uint32_t tile_width;
+
+ if (tiling_mode == I915_TILING_NONE)
+ return pitch;
+
+ if (tiling_mode == I915_TILING_Y && INTEL_HAS_128_BYTE_Y_TILING(dev))
+ tile_width = 128;
+ else
+ tile_width = 512;
+
+ /* 965+ just needs multiples of tile width */
+ if (INTEL_IS_I965(dev))
+ return align_to(pitch, tile_width);
+
+ /* Pre-965 needs power of two tile widths */
+ while (tile_width < pitch)
+ tile_width <<= 1;
+
+ return tile_width;
+}
+
+static uint32_t
+tiling_size(int dev, uint32_t tiling, uint32_t size)
+{
+ uint32_t fence;
+
+ if (tiling == I915_TILING_NONE)
+ return size;
+
+ /* The 965 can have fences at any page boundary. */
+ if (INTEL_IS_I965(dev))
+ return align_to(size, 4096);
+
+ /* Align the size to a power of two greater than the smallest fence. */
+ if (INTEL_IS_I9xx(dev))
+ fence = 1024 * 1024; /* 1 MiB */
+ else
+ fence = 512 * 1024; /* 512 KiB */
+ while (fence < size)
+ fence <<= 1;
+
+ return fence;
+}
+
static int
create_buffer(int fd, GLint width, GLint height, GLint cpp, __DRIbuffer *buffer)
{
struct drm_i915_gem_create create;
struct drm_gem_flink flink;
uint32_t size;
+ int tiling;
+ int dev = INTEL_GEN_4; /* XXX query using I915_GETPARAM + PARAM_CHIPSET_ID */
+ tiling = I915_TILING_X;
buffer->pitch = align_to(width * cpp, INTEL_STRIDE_ALIGNMENT);
- size = buffer->pitch * height;
+ if (tiling != I915_TILING_NONE) {
+ buffer->pitch = tiling_stride(dev, tiling, buffer->pitch);
+ size = buffer->pitch * height;
+ size = tiling_size(dev, tiling, size);
+ } else {
+ size = buffer->pitch * height;
+ }
+
create.size = size;
if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create)) {
LOGE("failed to create buffer");
return 0;
}
+ if (tiling != I915_TILING_NONE) {
+ struct drm_i915_gem_set_tiling set_tiling;
+
+ memset(&set_tiling, 0, sizeof(set_tiling));
+ set_tiling.handle = create.handle;
+ set_tiling.tiling_mode = tiling;
+ set_tiling.stride = buffer->pitch;
+
+ if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling))
+ LOGW("failed to enable tiling");
+ }
+
flink.handle = create.handle;
if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
LOGE("failed to flink buffer");