Skip to content

Instantly share code, notes, and snippets.

@xc-racer99
Last active February 16, 2020 00:34
Show Gist options
  • Save xc-racer99/b048eec95bdf3115cb0c3e2c266563f2 to your computer and use it in GitHub Desktop.
Save xc-racer99/b048eec95bdf3115cb0c3e2c266563f2 to your computer and use it in GitHub Desktop.
Experimental xf86-video-armsoc patches with Samsung g2d support
From dc3cf2048ff11cf6dd5b3233a2faee1662d73168 Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Tue, 3 Mar 2015 18:11:22 +0100
Subject: [PATCH 01/12] Remove InitFromFBDev
FBDev is legacy and we disable its support on
newer kernels anyway.
---
man/armsoc.man | 13 ----
src/armsoc_driver.c | 153 --------------------------------------------
2 files changed, 166 deletions(-)
diff --git a/man/armsoc.man b/man/armsoc.man
index d85c2fa..eb83127 100644
--- a/man/armsoc.man
+++ b/man/armsoc.man
@@ -50,19 +50,6 @@ Default: NULL
.BI "Option \*qDRICard\*q \*q" integer \*q
Select which dri card to use.
.IP
-Default: 0
-.TP
-.BI "Option \*qInitFromFBDev\*q \*q" string \*q
-Specifies an fbdev device node (such as "/dev/fb0") to use to initialize the
-DRM scanout buffer. Specifying this option only makes sense (and is required)
-when X is started with the parameter "-background none".
-
-The InitFromFBDev functionality is limited to when the fbdev device pixel
-format matches the format of the X screen. This includes bits-per-pixel and RGB
-ordering and size. If the driver is unable to copy from the fbdev device then
-an error will be logged, and the -background none functionality will be
-disabled.
-.IP
Default: NULL
.TP
.BI "Option \*qUMP_LOCK\*q \*q" boolean \*q
diff --git a/src/armsoc_driver.c b/src/armsoc_driver.c
index 83e74a7..41799f8 100644
--- a/src/armsoc_driver.c
+++ b/src/armsoc_driver.c
@@ -36,7 +36,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <linux/fb.h>
-#include <sys/ioctl.h>
#include <sys/mman.h>
#include <pixman.h>
@@ -107,7 +106,6 @@ enum {
OPTION_BUSID,
OPTION_DRIVERNAME,
OPTION_DRI_NUM_BUF,
- OPTION_INIT_FROM_FBDEV,
OPTION_UMP_LOCK,
};
@@ -119,7 +117,6 @@ static const OptionInfoRec ARMSOCOptions[] = {
{ OPTION_BUSID, "BusID", OPTV_STRING, {0}, FALSE },
{ OPTION_DRIVERNAME, "DriverName", OPTV_STRING, {0}, FALSE },
{ OPTION_DRI_NUM_BUF, "DRI2MaxBuffers", OPTV_INTEGER, {-1}, FALSE },
- { OPTION_INIT_FROM_FBDEV, "InitFromFBDev", OPTV_STRING, {0}, FALSE },
{ OPTION_UMP_LOCK, "UMP_LOCK", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -343,145 +340,6 @@ ARMSOCCloseDRM(ScrnInfoPtr pScrn)
}
}
-static Bool ARMSOCCopyFB(ScrnInfoPtr pScrn, const char *fb_dev)
-{
- struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
- int src_cpp;
- uint32_t src_pitch;
- int src_pixman_stride;
- int dst_pixman_stride;
- int dst_width, dst_height, dst_bpp, dst_pitch;
- unsigned int src_size = 0;
- unsigned char *src = NULL, *dst = NULL;
- struct fb_var_screeninfo vinfo;
- int fd = -1;
- int width, height;
- pixman_bool_t pixman_ret;
- Bool ret = FALSE;
-
- dst = armsoc_bo_map(pARMSOC->scanout);
- if (!dst) {
- ERROR_MSG("Couldn't map scanout bo");
- goto exit;
- }
-
- fd = open(fb_dev, O_RDONLY | O_SYNC);
- if (fd == -1) {
- ERROR_MSG("Couldn't open %s", fb_dev);
- goto exit;
- }
-
- if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
- ERROR_MSG("Vscreeninfo ioctl failed");
- goto exit;
- }
-
- src_cpp = (vinfo.bits_per_pixel + 7) / 8;
- src_pitch = vinfo.xres_virtual * src_cpp;
- src_size = vinfo.yres_virtual * src_pitch;
-
- src = mmap(NULL, src_size, PROT_READ, MAP_SHARED, fd, 0);
- if (src == MAP_FAILED) {
- ERROR_MSG("Couldn't mmap %s", fb_dev);
- goto exit;
- }
-
- dst_width = armsoc_bo_width(pARMSOC->scanout);
- dst_height = armsoc_bo_height(pARMSOC->scanout);
- dst_bpp = armsoc_bo_bpp(pARMSOC->scanout);
- dst_pitch = armsoc_bo_pitch(pARMSOC->scanout);
-
- width = min(vinfo.xres, dst_width);
- height = min(vinfo.yres, dst_height);
-
- /* The stride parameters pixman takes are in multiples of uint32_t,
- * which is the data type of the pointer passed */
- src_pixman_stride = src_pitch/sizeof(uint32_t);
- dst_pixman_stride = dst_pitch/sizeof(uint32_t);
-
- /* We could handle the cases where stride is not a multiple of uint32_t,
- * but they will be rare so not currently worth the added complexity */
- if (src_pitch%sizeof(uint32_t) || dst_pitch%sizeof(uint32_t)) {
- ERROR_MSG(
- "Buffer strides need to be a multiple of 4 bytes to initialize from fbdev device");
- goto exit;
- }
-
- /* similarly using pixman_blt doesn't allow for format conversion, so
- * check if they don't match and print a message */
- if (vinfo.bits_per_pixel != dst_bpp || vinfo.grayscale != 0 ||
- vinfo.nonstd != 0 ||
- vinfo.red.offset != pScrn->offset.red ||
- vinfo.red.length != pScrn->weight.red ||
- vinfo.red.msb_right != 0 ||
- vinfo.green.offset != pScrn->offset.green ||
- vinfo.green.length != pScrn->weight.green ||
- vinfo.green.msb_right != 0 ||
- vinfo.blue.offset != pScrn->offset.blue ||
- vinfo.blue.length != pScrn->weight.blue ||
- vinfo.blue.msb_right != 0) {
- ERROR_MSG("Format of %s does not match scanout buffer", fb_dev);
- goto exit;
- }
-
- armsoc_bo_cpu_prep(pARMSOC->scanout, ARMSOC_GEM_WRITE);
-
- /* NB: We have to call pixman direct instead of wrapping the buffers as
- * Pixmaps as this function is called from ScreenInit. Pixmaps cannot be
- * created until X calls CreateScratchPixmapsForScreen(), and the screen
- * pixmap is not initialized until X calls CreateScreenResources */
- pixman_ret = pixman_blt((uint32_t *)src, (uint32_t *)dst,
- src_pixman_stride, dst_pixman_stride,
- vinfo.bits_per_pixel, dst_bpp, vinfo.xoffset,
- vinfo.yoffset, 0, 0, width, height);
- if (!pixman_ret) {
- armsoc_bo_cpu_fini(pARMSOC->scanout, 0);
- ERROR_MSG("Pixman failed to blit from %s to scanout buffer",
- fb_dev);
- goto exit;
- }
-
- /* fill any area not covered by the blit */
- if (width < dst_width) {
- pixman_ret = pixman_fill((uint32_t *)dst, dst_pixman_stride,
- dst_bpp, width, 0, dst_width-width, dst_height,
- 0);
- if (!pixman_ret) {
- armsoc_bo_cpu_fini(pARMSOC->scanout, 0);
- ERROR_MSG(
- "Pixman failed to fill margin of scanout buffer");
- goto exit;
- }
- }
-
- if (height < dst_height) {
- pixman_ret = pixman_fill((uint32_t *)dst, dst_pixman_stride,
- dst_bpp, 0, height, width, dst_height-height,
- 0);
- if (!pixman_ret) {
- armsoc_bo_cpu_fini(pARMSOC->scanout, 0);
- ERROR_MSG(
- "Pixman failed to fill margin of scanout buffer");
- goto exit;
- }
- }
-
- armsoc_bo_cpu_fini(pARMSOC->scanout, 0);
-
- ret = TRUE;
-
-exit:
- if (src)
- munmap(src, src_size);
-
- if (fd >= 0)
- close(fd);
-
- return ret;
-}
-
-
-
/** Let the XFree86 code know the Setup() function. */
static MODULESETUPPROTO(ARMSOCSetup);
@@ -986,7 +844,6 @@ ARMSOCScreenInit(SCREEN_INIT_ARGS_DECL)
VisualPtr visual;
xf86CrtcConfigPtr xf86_config;
int j;
- const char *fbdev;
int depth;
TRACE_ENTER();
@@ -1102,16 +959,6 @@ ARMSOCScreenInit(SCREEN_INIT_ARGS_DECL)
/* Initialize backing store: */
xf86SetBackingStore(pScreen);
- fbdev = xf86GetOptValString(pARMSOC->pOptionInfo,
- OPTION_INIT_FROM_FBDEV);
- if (fbdev && *fbdev != '\0') {
- if (ARMSOCCopyFB(pScrn, fbdev)) {
- /* Only allow None BG root if we initialized the scanout
- * buffer */
- pScreen->canDoBGNoneRoot = TRUE;
- }
- }
-
/* Enable cursor position updates by mouse signal handler: */
xf86SetSilkenMouse(pScreen);
--
2.20.1
From 87d59b72af43ab708d164dba1745a5dd65c0c2ff Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Thu, 11 Jun 2015 17:14:30 +0200
Subject: [PATCH 02/12] exynos: remove custom cursor plane init
DRM plane handling has largely changed in newer
kernel versions. In particular the 'zpos'
property of a plane is now immutable after the
move to the atomic framework.
---
src/drmmode_exynos/drmmode_exynos.c | 45 +----------------------------
1 file changed, 1 insertion(+), 44 deletions(-)
diff --git a/src/drmmode_exynos/drmmode_exynos.c b/src/drmmode_exynos/drmmode_exynos.c
index 6b79522..46cf22f 100644
--- a/src/drmmode_exynos/drmmode_exynos.c
+++ b/src/drmmode_exynos/drmmode_exynos.c
@@ -69,49 +69,6 @@ struct drm_exynos_gem_create {
#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
-static int init_plane_for_cursor(int drm_fd, uint32_t plane_id)
-{
- int res = -1;
- drmModeObjectPropertiesPtr props;
- props = drmModeObjectGetProperties(drm_fd, plane_id,
- DRM_MODE_OBJECT_PLANE);
-
- if (props) {
- int i;
-
- for (i = 0; i < props->count_props; i++) {
- drmModePropertyPtr this_prop;
- this_prop = drmModeGetProperty(drm_fd, props->props[i]);
-
- if (this_prop) {
- if (!strncmp(this_prop->name, "zpos",
- DRM_PROP_NAME_LEN)) {
- res = drmModeObjectSetProperty(drm_fd,
- plane_id,
- DRM_MODE_OBJECT_PLANE,
- this_prop->prop_id,
- 1);
- drmModeFreeProperty(this_prop);
- break;
- }
- drmModeFreeProperty(this_prop);
- }
- }
- drmModeFreeObjectProperties(props);
- }
-
- if (res) {
- /* Try the old method */
- struct drm_exynos_plane_set_zpos data;
- data.plane_id = plane_id;
- data.zpos = 1;
-
- res = ioctl(drm_fd, DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS, &data);
- }
-
- return res;
-}
-
static int create_custom_gem(int fd, struct armsoc_create_gem *create_gem)
{
struct drm_exynos_gem_create create_exynos;
@@ -152,7 +109,7 @@ struct drmmode_interface exynos_interface = {
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
HWCURSOR_API_PLANE /* cursor_api */,
- init_plane_for_cursor /* init_plane_for_cursor */,
+ NULL /* init_plane_for_cursor */,
0 /* vblank_query_supported */,
create_custom_gem /* create_custom_gem */,
};
--
2.20.1
From f37be67d63e33258a42ada378bf637784c8c4812 Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Thu, 11 Jun 2015 17:15:40 +0200
Subject: [PATCH 03/12] exynos: zpos ioctl cleanup
The ioctl defines and the corresponding struct are
no longer needed.
---
src/drmmode_exynos/drmmode_exynos.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/src/drmmode_exynos/drmmode_exynos.c b/src/drmmode_exynos/drmmode_exynos.c
index 46cf22f..b7734de 100644
--- a/src/drmmode_exynos/drmmode_exynos.c
+++ b/src/drmmode_exynos/drmmode_exynos.c
@@ -28,17 +28,6 @@
#include <xf86drm.h>
#include <sys/ioctl.h>
-/* Following ioctls should be included from libdrm exynos_drm.h but
- * libdrm doesn't install this correctly so for now they are here.
- */
-struct drm_exynos_plane_set_zpos {
- __u32 plane_id;
- __s32 zpos;
-};
-#define DRM_EXYNOS_PLANE_SET_ZPOS 0x06
-#define DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS DRM_IOWR(DRM_COMMAND_BASE + \
- DRM_EXYNOS_PLANE_SET_ZPOS, struct drm_exynos_plane_set_zpos)
-
#define EXYNOS_BO_CONTIG 0
#define EXYNOS_BO_NONCONTIG 1
--
2.20.1
From 48e6724ec82b2a3afeeb9e2c392b082dff643268 Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Fri, 12 Jun 2015 10:59:34 +0200
Subject: [PATCH 04/12] Rewrite cursor plane initialization
Iterate over all overlay planes and find the
plane with the highest 'zpos' property.
---
src/drmmode_display.c | 98 ++++++++++++++++++++++++++++++-------------
1 file changed, 69 insertions(+), 29 deletions(-)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 39fa75c..08dd3ca 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -626,6 +626,40 @@ drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
drmmode_show_cursor_image(crtc, TRUE);
}
+/* Get 'zpos' property from DRM plane. */
+static int
+drmmode_plane_zpos(int drm_fd, drmModePlane *plane)
+{
+ unsigned int i;
+ int ret = -1;
+ drmModeObjectPropertiesPtr props;
+
+ props = drmModeObjectGetProperties(drm_fd, plane->plane_id,
+ DRM_MODE_OBJECT_PLANE);
+
+ if (!props)
+ goto out;
+
+ for (i = 0; i < props->count_props; i++) {
+ drmModePropertyPtr prop;
+ prop = drmModeGetProperty(drm_fd, props->props[i]);
+ if (!prop)
+ continue;
+
+ if (!strncmp(prop->name, "zpos", DRM_PROP_NAME_LEN))
+ ret = props->prop_values[i];
+
+ drmModeFreeProperty(prop);
+
+ if (ret != -1)
+ break;
+ }
+
+out:
+ drmModeFreeObjectProperties(props);
+ return ret;
+}
+
static Bool
drmmode_cursor_init_plane(ScreenPtr pScreen)
{
@@ -634,7 +668,7 @@ drmmode_cursor_init_plane(ScreenPtr pScreen)
struct drmmode_rec *drmmode = drmmode_from_scrn(pScrn);
struct drmmode_cursor_rec *cursor;
drmModePlaneRes *plane_resources;
- drmModePlane *ovr;
+ drmModePlane *ovr = NULL;
int w, h, pad;
uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */
@@ -660,34 +694,39 @@ drmmode_cursor_init_plane(ScreenPtr pScreen)
return FALSE;
}
- if (plane_resources->count_planes < 1) {
+ if (plane_resources->count_planes > 0) {
+ unsigned int i;
+ int temp, z = -1;
+ drmModePlane *p;
+
+ for (i = 0; i < plane_resources->count_planes; i++) {
+ p = drmModeGetPlane(drmmode->fd, plane_resources->planes[i]);
+ if (!p) {
+ ERROR_MSG("HW cursor: drmModeGetPlane failed: %s",
+ strerror(errno));
+ goto fail_plane_res;
+ }
+
+ temp = drmmode_plane_zpos(drmmode->fd, p);
+ if (temp > z) {
+ z = temp;
+ ovr = p;
+ }
+ }
+ } else {
ERROR_MSG("not enough planes for HW cursor");
- drmModeFreePlaneResources(plane_resources);
- return FALSE;
+ goto fail_plane_res;
}
- ovr = drmModeGetPlane(drmmode->fd, plane_resources->planes[0]);
if (!ovr) {
- ERROR_MSG("HW cursor: drmModeGetPlane failed: %s",
- strerror(errno));
- drmModeFreePlaneResources(plane_resources);
- return FALSE;
- }
-
- if (pARMSOC->drmmode_interface->init_plane_for_cursor &&
- pARMSOC->drmmode_interface->init_plane_for_cursor(
- drmmode->fd, ovr->plane_id)) {
- ERROR_MSG("Failed driver-specific cursor initialization");
- drmModeFreePlaneResources(plane_resources);
- return FALSE;
+ ERROR_MSG("HW cursor: no suitable plane found");
+ goto fail_plane_res;
}
cursor = calloc(1, sizeof(struct drmmode_cursor_rec));
if (!cursor) {
ERROR_MSG("HW cursor: calloc failed");
- drmModeFreePlane(ovr);
- drmModeFreePlaneResources(plane_resources);
- return FALSE;
+ goto fail_plane;
}
cursor->ovr = ovr;
@@ -704,9 +743,7 @@ drmmode_cursor_init_plane(ScreenPtr pScreen)
if (!cursor->bo) {
ERROR_MSG("HW cursor: buffer allocation failed");
free(cursor);
- drmModeFreePlane(ovr);
- drmModeFreePlaneResources(plane_resources);
- return FALSE;
+ goto fail_plane;
}
handles[0] = armsoc_bo_handle(cursor->bo);
@@ -720,9 +757,7 @@ drmmode_cursor_init_plane(ScreenPtr pScreen)
strerror(errno));
armsoc_bo_unreference(cursor->bo);
free(cursor);
- drmModeFreePlane(ovr);
- drmModeFreePlaneResources(plane_resources);
- return FALSE;
+ goto fail_plane;
}
if (!xf86_cursors_init(pScreen, w, h, HARDWARE_CURSOR_ARGB)) {
@@ -732,15 +767,20 @@ drmmode_cursor_init_plane(ScreenPtr pScreen)
armsoc_bo_unreference(cursor->bo);
free(cursor);
- drmModeFreePlane(ovr);
- drmModeFreePlaneResources(plane_resources);
- return FALSE;
+ goto fail_plane;
}
INFO_MSG("HW cursor initialized");
drmmode->cursor = cursor;
drmModeFreePlaneResources(plane_resources);
return TRUE;
+
+fail_plane:
+ drmModeFreePlane(ovr);
+
+fail_plane_res:
+ drmModeFreePlaneResources(plane_resources);
+ return FALSE;
}
static Bool
--
2.20.1
From 648adc04ddd23f120fb7768f12f38a2cca8ab074 Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Fri, 12 Jun 2015 11:01:50 +0200
Subject: [PATCH 05/12] Remove init_plane_for_cursor() from drmmode_interface
This callback is no longer used with the current code.
---
src/drmmode_driver.h | 15 ---------------
src/drmmode_exynos/drmmode_exynos.c | 1 -
src/drmmode_kirin/drmmode_kirin.c | 1 -
src/drmmode_pl111/drmmode_pl111.c | 1 -
src/drmmode_sti/drmmode_sti.c | 6 ------
src/drmmode_template/drmmode_template.c | 7 -------
6 files changed, 31 deletions(-)
diff --git a/src/drmmode_driver.h b/src/drmmode_driver.h
index 879fc60..24a3d16 100644
--- a/src/drmmode_driver.h
+++ b/src/drmmode_driver.h
@@ -70,21 +70,6 @@ struct drmmode_interface {
*/
enum hwcursor_api cursor_api;
- /* (Optional) Initialize the hardware cursor plane.
- *
- * When cursor_api is HWCURSOR_API_PLANE, this function should do any
- * plane initialization necessary, for example setting the z-order on the
- * plane to appear above all other layers. If this function fails the driver
- * falls back to using a software cursor.
- *
- * If cursor_api is not HWCURSOR_API_PLANE this function should be omitted.
- *
- * @param drm_fd The DRM device file
- * @param plane_id The plane to initialize
- * @return 0 on success, non-zero on failure
- */
- int (*init_plane_for_cursor)(int drm_fd, uint32_t plane_id);
-
/* Boolean value indicating whether the DRM supports
* vblank timestamp query
*/
diff --git a/src/drmmode_exynos/drmmode_exynos.c b/src/drmmode_exynos/drmmode_exynos.c
index b7734de..c35305b 100644
--- a/src/drmmode_exynos/drmmode_exynos.c
+++ b/src/drmmode_exynos/drmmode_exynos.c
@@ -98,7 +98,6 @@ struct drmmode_interface exynos_interface = {
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
HWCURSOR_API_PLANE /* cursor_api */,
- NULL /* init_plane_for_cursor */,
0 /* vblank_query_supported */,
create_custom_gem /* create_custom_gem */,
};
diff --git a/src/drmmode_kirin/drmmode_kirin.c b/src/drmmode_kirin/drmmode_kirin.c
index f956a9b..d77ac5b 100644
--- a/src/drmmode_kirin/drmmode_kirin.c
+++ b/src/drmmode_kirin/drmmode_kirin.c
@@ -88,7 +88,6 @@ struct drmmode_interface kirin_interface = {
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
HWCURSOR_API_NONE /* software cursor */,
- NULL /* no plane for cursor */,
0 /* vblank_query_supported */,
create_custom_gem /* create_custom_gem */,
};
diff --git a/src/drmmode_pl111/drmmode_pl111.c b/src/drmmode_pl111/drmmode_pl111.c
index 162bb41..5b69f27 100644
--- a/src/drmmode_pl111/drmmode_pl111.c
+++ b/src/drmmode_pl111/drmmode_pl111.c
@@ -113,7 +113,6 @@ struct drmmode_interface pl111_interface = {
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
HWCURSOR_API_STANDARD /* cursor_api */,
- NULL /* init_plane_for_cursor */,
0 /* vblank_query_supported */,
create_custom_gem /* create_custom_gem */,
};
diff --git a/src/drmmode_sti/drmmode_sti.c b/src/drmmode_sti/drmmode_sti.c
index 5cc7c01..56daa58 100644
--- a/src/drmmode_sti/drmmode_sti.c
+++ b/src/drmmode_sti/drmmode_sti.c
@@ -57,11 +57,6 @@ for a bug
*/
#define CURSORPAD (16)
-/* Optional function */
-static int init_plane_for_cursor(int drm_fd, uint32_t plane_id) {
- return 0;
-}
-
static int create_custom_gem(int fd, struct armsoc_create_gem
*create_gem) {
struct drm_mode_create_dumb create_arg;
@@ -92,7 +87,6 @@ struct drmmode_interface sti_interface = {
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
HWCURSOR_API_STANDARD /* cursor_api */,
- init_plane_for_cursor /* init_plane_for_cursor */,
0 /* vblank_query_supported */,
create_custom_gem /* create_custom_gem */,
};
diff --git a/src/drmmode_template/drmmode_template.c b/src/drmmode_template/drmmode_template.c
index 8c4a6b4..6375cb6 100644
--- a/src/drmmode_template/drmmode_template.c
+++ b/src/drmmode_template/drmmode_template.c
@@ -37,12 +37,6 @@
/* Padding added down each side of cursor image */
#define CURSORPAD (0)
-/* Optional function only for HWCURSOR_API_PLANE interface */
-static int init_plane_for_cursor(int drm_fd, uint32_t plane_id)
-{
- return 0;
-}
-
static int create_custom_gem(int fd, struct armsoc_create_gem *create_gem)
{
/*
@@ -60,7 +54,6 @@ struct drmmode_interface template_interface = {
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
HWCURSOR_API_STANDARD /* cursor_api */,
- init_plane_for_cursor /* init_plane_for_cursor */,
0 /* vblank_query_supported */,
create_custom_gem /* create_custom_gem */,
};
--
2.20.1
From 43e327f953b845656278e4cd8719ed2646449c51 Mon Sep 17 00:00:00 2001
From: Daniel Drake <drake@endlessm.com>
Date: Thu, 30 Jan 2014 21:28:00 +0000
Subject: [PATCH 06/12] exynos: create write-combining memory maps
We were always requesting uncacheable memory here. Oops.
Now we ask for write-combining, resulting in a return to the land of
normal 2D graphics speeds.
Need to check that the write-combine buffer gets cleared at appropriate
times.
Basic performance differences:
| BEFORE BEFORE | AFTER AFTER
| RAW X MUTTER | RAW X MUTTER
----------------+-------------------+----------------
glxgears (fps) | 149 141 | 148 140
es2gears (fps) | 153 177 | 313 290
glmark-es2 | 34 35 | 91 68
gtkperf (time) | 20.47 23.3 | 10.7 13.6
---
src/drmmode_exynos/drmmode_exynos.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/src/drmmode_exynos/drmmode_exynos.c b/src/drmmode_exynos/drmmode_exynos.c
index c35305b..536b1af 100644
--- a/src/drmmode_exynos/drmmode_exynos.c
+++ b/src/drmmode_exynos/drmmode_exynos.c
@@ -28,8 +28,20 @@
#include <xf86drm.h>
#include <sys/ioctl.h>
-#define EXYNOS_BO_CONTIG 0
-#define EXYNOS_BO_NONCONTIG 1
+enum e_drm_exynos_gem_mem_type {
+ /* Physically Continuous memory and used as default. */
+ EXYNOS_BO_CONTIG = 0 << 0,
+ /* Physically Non-Continuous memory. */
+ EXYNOS_BO_NONCONTIG = 1 << 0,
+ /* non-cachable mapping and used as default. */
+ EXYNOS_BO_NONCACHABLE = 0 << 1,
+ /* cachable mapping. */
+ EXYNOS_BO_CACHABLE = 1 << 1,
+ /* write-combine mapping. */
+ EXYNOS_BO_WC = 1 << 2,
+ EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG | EXYNOS_BO_CACHABLE |
+ EXYNOS_BO_WC
+};
struct drm_exynos_gem_create {
uint64_t size;
@@ -76,7 +88,7 @@ static int create_custom_gem(int fd, struct armsoc_create_gem *create_gem)
* When they are supported all allocations are effectively contiguous
* anyway, so for simplicity we always request non contiguous buffers.
*/
- create_exynos.flags = EXYNOS_BO_NONCONTIG;
+ create_exynos.flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
ret = drmIoctl(fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &create_exynos);
if (ret)
--
2.20.1
From ddb1a670d335e559728a025ae610f5fd2b35902c Mon Sep 17 00:00:00 2001
From: Daniel Drake <drake@endlessm.com>
Date: Tue, 8 Apr 2014 11:49:45 -0600
Subject: [PATCH 07/12] Only allocate DRI2 pixmaps with GEM
The driver is currently set up (via EXA) to handle all pixmap allocations
itself, and it passes them to GEM.
However, running non-3D apps tends to generate a large number of small
pixmap allocations that we're never going to pass to GL, and it is
expensive and pointless to send them through GEM in this case.
To solve this, fbturbo and my earlier armsoc work for r3p2 strips out EXA,
falling back to X's fast default implementation of pixmap allocation in
the fb layer, then we would migrate such pixmaps to GEM the first time
DRI2 interaction is requested.
However, especially with growing interest in using the CPU cache for a
future performance increase, EXA's PrepareAccess and FinishAccess hooks
are looking more and more useful. In order to use them, we also have to
take over allocation of all pixmaps, but we can do it better: we can
use usage_hint to determine which pixmaps are backing buffers for windows
(hence likely candidates for DRI2 interaction) and which aren't.
The only remaining complication is to detect which pixmap is going to be
used for scanout, this is a bit hacky but it seems to always be the first
pixmap created after ScreenInit.
Performance differences (at 1080p):
| BEFORE BEFORE | AFTER AFTER
| RAW X MUTTER | RAW X MUTTER
----------------+-------------------+----------------
glxgears (fps) | 148 140 | 148 137
es2gears (fps) | 313 290 | 313 295
glmark-es2 | 91 68 | 91 73
gtkperf (time) | 10.7 13.6 | 7.3 9.7
---
src/armsoc_dri2.c | 2 +-
src/armsoc_driver.c | 2 +
src/armsoc_driver.h | 5 ++
src/armsoc_exa.c | 179 ++++++++++++++++++++++++++++++++++++++------
src/armsoc_exa.h | 2 +
5 files changed, 168 insertions(+), 22 deletions(-)
diff --git a/src/armsoc_dri2.c b/src/armsoc_dri2.c
index dc502e4..3a61c63 100755
--- a/src/armsoc_dri2.c
+++ b/src/armsoc_dri2.c
@@ -141,7 +141,7 @@ static PixmapPtr
createpix(DrawablePtr pDraw)
{
ScreenPtr pScreen = pDraw->pScreen;
- int flags = canflip(pDraw) ? ARMSOC_CREATE_PIXMAP_SCANOUT : 0;
+ int flags = canflip(pDraw) ? ARMSOC_CREATE_PIXMAP_SCANOUT : CREATE_PIXMAP_USAGE_BACKING_PIXMAP;
return pScreen->CreatePixmap(pScreen,
pDraw->width, pDraw->height, pDraw->depth, flags);
}
diff --git a/src/armsoc_driver.c b/src/armsoc_driver.c
index 41799f8..a8cafe3 100644
--- a/src/armsoc_driver.c
+++ b/src/armsoc_driver.c
@@ -848,6 +848,8 @@ ARMSOCScreenInit(SCREEN_INIT_ARGS_DECL)
TRACE_ENTER();
+ pARMSOC->created_scanout_pixmap = FALSE;
+
/* set drm master before allocating scanout buffer */
if (ARMSOCSetDRMMaster()) {
ERROR_MSG("Cannot get DRM master: %s", strerror(errno));
diff --git a/src/armsoc_driver.h b/src/armsoc_driver.h
index ef2836f..ac260d7 100644
--- a/src/armsoc_driver.h
+++ b/src/armsoc_driver.h
@@ -180,6 +180,11 @@ struct ARMSOCRec {
/* Size of the swap chain. Set to 1 if DRI2SwapLimit unsupported,
* driNumBufs if early display enabled, otherwise driNumBufs-1 */
unsigned int swap_chain_size;
+
+ /* The first CreatePixmap after ScreenInit ends up being the
+ * scanout, but we don't get any usage hint indicating that it should
+ * be accelerated. Use a flag to detect this and act accordingly. */
+ Bool created_scanout_pixmap;
};
/*
diff --git a/src/armsoc_exa.c b/src/armsoc_exa.c
index a310727..c58db80 100644
--- a/src/armsoc_exa.c
+++ b/src/armsoc_exa.c
@@ -35,6 +35,16 @@
#include <sys/ioctl.h>
#include <unistd.h>
+static Bool is_accel_pixmap(struct ARMSOCPixmapPrivRec *priv)
+{
+ /* For pixmaps that are scanout or backing for windows, we
+ * "accelerate" them by allocating them via GEM. For all other
+ * pixmaps (where we never expect DRI2 CreateBuffer to be called), we
+ * just malloc them, which turns out to be much faster.
+ */
+ return priv->usage_hint == ARMSOC_CREATE_PIXMAP_SCANOUT || priv->usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP;
+}
+
/* keep this here, instead of static-inline so submodule doesn't
* need to know layout of ARMSOCRec.
*/
@@ -75,20 +85,40 @@ ARMSOCPixmapExchange(PixmapPtr a, PixmapPtr b)
}
}
-_X_EXPORT void *
-ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height,
- int depth, int usage_hint, int bitsPerPixel,
+static void *
+CreateNoAccelPixmap(struct ARMSOCPixmapPrivRec *priv, ScreenPtr pScreen, int width, int height,
+ int depth, int bitsPerPixel,
+ int *new_fb_pitch)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+
+ if (width > 0 && height > 0 && depth > 0 && bitsPerPixel > 0) {
+ int pitch = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ size_t datasize = pitch * height;
+ priv->unaccel = malloc(datasize);
+
+ if (!priv->unaccel) {
+ ERROR_MSG("failed to allocate %dx%d mem", width, height);
+ free(priv);
+ return NULL;
+ }
+ priv->unaccel_size = datasize;
+ *new_fb_pitch = pitch;
+ }
+
+ return priv;
+}
+
+static void *
+CreateAccelPixmap(struct ARMSOCPixmapPrivRec *priv, ScreenPtr pScreen, int width, int height,
+ int depth, int bitsPerPixel,
int *new_fb_pitch)
{
- struct ARMSOCPixmapPrivRec *priv = calloc(1, sizeof(*priv));
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
enum armsoc_buf_type buf_type = ARMSOC_BO_NON_SCANOUT;
- if (!priv)
- return NULL;
-
- if (usage_hint & ARMSOC_CREATE_PIXMAP_SCANOUT)
+ if (priv->usage_hint == ARMSOC_CREATE_PIXMAP_SCANOUT)
buf_type = ARMSOC_BO_SCANOUT;
if (width > 0 && height > 0 && depth > 0 && bitsPerPixel > 0) {
@@ -123,15 +153,32 @@ ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height,
*new_fb_pitch = armsoc_bo_pitch(priv->bo);
}
- /* The usage_hint field of the Pixmap passed to ModifyPixmapHeader is
- * not set to the usage_hint parameter passed to CreatePixmap.
- * It does appear to be set here so we stash it in the private
- * structure. However as we do not fully understand the uses of this
- * parameter, beware of any unexpected values!
- */
+ return priv;
+}
+
+_X_EXPORT void *
+ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height,
+ int depth, int usage_hint, int bitsPerPixel,
+ int *new_fb_pitch)
+{
+ struct ARMSOCPixmapPrivRec *priv =
+ calloc(sizeof(struct ARMSOCPixmapPrivRec), 1);
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
+
+ if (!priv)
+ return NULL;
+
+ if (!pARMSOC->created_scanout_pixmap) {
+ usage_hint = ARMSOC_CREATE_PIXMAP_SCANOUT;
+ pARMSOC->created_scanout_pixmap = TRUE;
+ }
priv->usage_hint = usage_hint;
- return priv;
+ if (is_accel_pixmap(priv))
+ return CreateAccelPixmap(priv, pScreen, width, height, depth, bitsPerPixel, new_fb_pitch);
+ else
+ return CreateNoAccelPixmap(priv, pScreen, width, height, depth, bitsPerPixel, new_fb_pitch);
}
_X_EXPORT void
@@ -149,15 +196,87 @@ ARMSOCDestroyPixmap(ScreenPtr pScreen, void *driverPriv)
armsoc_bo_unreference(priv->bo);
}
+ if (priv->unaccel)
+ free(priv->unaccel);
+
free(priv);
}
-_X_EXPORT Bool
-ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+static Bool
+ModifyUnAccelPixmapHeader(struct ARMSOCPixmapPrivRec *priv, PixmapPtr pPixmap, int width, int height,
+ int depth, int bitsPerPixel, int devKind,
+ pointer pPixData)
+{
+ ScrnInfoPtr pScrn = pix2scrn(pPixmap);
+ size_t datasize;
+
+ /* Only modify specified fields, keeping all others intact. */
+ if (pPixData)
+ pPixmap->devPrivate.ptr = pPixData;
+
+ if (devKind > 0)
+ pPixmap->devKind = devKind;
+
+ /*
+ * Someone is messing with the memory allocation. Let's step out of
+ * the picture.
+ */
+ if (pPixData && pPixData != priv->unaccel) {
+ if (priv->unaccel)
+ free(priv->unaccel);
+ priv->unaccel = NULL;
+ priv->unaccel_size = 0;
+
+ /* Returning FALSE calls miModifyPixmapHeader */
+ return FALSE;
+ }
+
+ if (depth > 0)
+ pPixmap->drawable.depth = depth;
+
+ if (bitsPerPixel > 0)
+ pPixmap->drawable.bitsPerPixel = bitsPerPixel;
+
+ if (width > 0)
+ pPixmap->drawable.width = width;
+
+ if (height > 0)
+ pPixmap->drawable.height = height;
+
+ /*
+ * X will sometimes create an empty pixmap (width/height == 0) and then
+ * use ModifyPixmapHeader to point it at PixData. We'll hit this path
+ * during the CreatePixmap call. Just return true and skip the allocate
+ * in this case.
+ */
+ if (!pPixmap->drawable.width || !pPixmap->drawable.height)
+ return TRUE;
+
+ datasize = devKind * height;
+ if (!priv->unaccel || priv->unaccel_size != datasize) {
+ /* re-allocate buffer! */
+ if (priv->unaccel)
+ free(priv->unaccel);
+ priv->unaccel = malloc(datasize);
+
+ if (!priv->unaccel) {
+ ERROR_MSG("failed to allocate %d bytes mem",
+ datasize);
+ priv->unaccel_size = 0;
+ return FALSE;
+ }
+ priv->unaccel_size = datasize;
+ }
+
+ return TRUE;
+}
+
+
+static Bool
+ModifyAccelPixmapHeader(struct ARMSOCPixmapPrivRec *priv, PixmapPtr pPixmap, int width, int height,
int depth, int bitsPerPixel, int devKind,
pointer pPixData)
{
- struct ARMSOCPixmapPrivRec *priv = exaGetPixmapDriverPrivate(pPixmap);
ScrnInfoPtr pScrn = pix2scrn(pPixmap);
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
enum armsoc_buf_type buf_type = ARMSOC_BO_NON_SCANOUT;
@@ -201,7 +320,7 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
}
}
- if (priv->usage_hint & ARMSOC_CREATE_PIXMAP_SCANOUT)
+ if (priv->usage_hint == ARMSOC_CREATE_PIXMAP_SCANOUT)
buf_type = ARMSOC_BO_SCANOUT;
if (depth > 0)
@@ -265,6 +384,18 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
return TRUE;
}
+_X_EXPORT Bool
+ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+ int depth, int bitsPerPixel, int devKind,
+ pointer pPixData)
+{
+ struct ARMSOCPixmapPrivRec *priv = exaGetPixmapDriverPrivate(pPixmap);
+ if (is_accel_pixmap(priv))
+ return ModifyAccelPixmapHeader(priv, pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData);
+ else
+ return ModifyUnAccelPixmapHeader(priv, pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData);
+}
+
/**
* WaitMarker is a required EXA callback but synchronization is
* performed during ARMSOCPrepareAccess so this function does not
@@ -335,6 +466,11 @@ ARMSOCPrepareAccess(PixmapPtr pPixmap, int index)
int ret;
struct ARMSOCPixmapPrivRec *priv = exaGetPixmapDriverPrivate(pPixmap);
+ if (!is_accel_pixmap(priv)) {
+ pPixmap->devPrivate.ptr = priv->unaccel;
+ return TRUE;
+ }
+
pPixmap->devPrivate.ptr = armsoc_bo_map(priv->bo);
if (!pPixmap->devPrivate.ptr) {
xf86DrvMsg(-1, X_ERROR, "%s: Failed to map buffer\n", __func__);
@@ -426,7 +562,8 @@ ARMSOCFinishAccess(PixmapPtr pPixmap, int index)
* do a more precise cache flush..
*/
pPixmap->devPrivate.ptr = NULL;
- armsoc_bo_cpu_fini(priv->bo, idx2op(index));
+ if (is_accel_pixmap(priv))
+ armsoc_bo_cpu_fini(priv->bo, idx2op(index));
}
}
@@ -454,7 +591,7 @@ ARMSOCPixmapIsOffscreen(PixmapPtr pPixmap)
* wrap this function.
*/
struct ARMSOCPixmapPrivRec *priv = exaGetPixmapDriverPrivate(pPixmap);
- return priv && priv->bo;
+ return priv && (priv->bo || priv->unaccel);
}
void ARMSOCRegisterExternalAccess(PixmapPtr pPixmap)
diff --git a/src/armsoc_exa.h b/src/armsoc_exa.h
index 002b351..6cae565 100644
--- a/src/armsoc_exa.h
+++ b/src/armsoc_exa.h
@@ -103,6 +103,8 @@ struct ARMSOCPixmapPrivRec {
*/
int ext_access_cnt;
struct armsoc_bo *bo;
+ unsigned char *unaccel;
+ size_t unaccel_size;
int usage_hint;
};
--
2.20.1
From fe0fee041d1aaa5d900f7530bf21c5fad8560734 Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Fri, 12 Jun 2015 13:54:59 +0200
Subject: [PATCH 08/12] Make is_accel_pixmap() available
Remove static from is_accel_pixmap() so we can use it
in the upcoming EXA implementation.
---
src/armsoc_exa.c | 2 +-
src/armsoc_exa.h | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/armsoc_exa.c b/src/armsoc_exa.c
index c58db80..1f0af42 100644
--- a/src/armsoc_exa.c
+++ b/src/armsoc_exa.c
@@ -35,7 +35,7 @@
#include <sys/ioctl.h>
#include <unistd.h>
-static Bool is_accel_pixmap(struct ARMSOCPixmapPrivRec *priv)
+Bool is_accel_pixmap(struct ARMSOCPixmapPrivRec *priv)
{
/* For pixmaps that are scanout or backing for windows, we
* "accelerate" them by allocating them via GEM. For all other
diff --git a/src/armsoc_exa.h b/src/armsoc_exa.h
index 6cae565..1eab09f 100644
--- a/src/armsoc_exa.h
+++ b/src/armsoc_exa.h
@@ -39,6 +39,9 @@
#include "exa.h"
#include "compat-api.h"
+/* Forward declarations: */
+struct ARMSOCPixmapPrivRec;
+
/**
* A per-Screen structure used to communicate and coordinate between the
* ARMSOC X driver and an external EXA sub-module (if loaded).
@@ -69,6 +72,7 @@ struct ARMSOCEXARec *InitNullEXA(ScreenPtr pScreen, ScrnInfoPtr pScrn, int fd);
struct ARMSOCEXARec *ARMSOCEXAPTR(ScrnInfoPtr pScrn);
+Bool is_accel_pixmap(struct ARMSOCPixmapPrivRec *priv);
static inline ScrnInfoPtr
pix2scrn(PixmapPtr pPixmap)
--
2.20.1
From 69b78defe71ac92f8b96b8b26a662b8020156aa5 Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Fri, 13 May 2016 11:42:05 +0200
Subject: [PATCH 09/12] Document the DRI2MaxBuffers option in the manpage
The option was added in commit 4198c8754c20641f41abc37959c355641fbfa383.
---
man/armsoc.man | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/man/armsoc.man b/man/armsoc.man
index eb83127..a47da60 100644
--- a/man/armsoc.man
+++ b/man/armsoc.man
@@ -56,6 +56,13 @@ Default: NULL
Use the umplock module for cross-process access synchronization. It should be only enabled for Mali400
.IP
Default: Umplock is Disabled
+Default: 0
+.TP
+.BI "Option \*qDRI2MaxBuffers\*q \*q" integer \*q
+Sets the number of buffers used when doing rendering
+through DRI2. Currently defaults to double buffering.
+.IP
+Default: -1
.SH DRM DEVICE SELECTION
--
2.20.1
From abd235661d6c07787ee8d40b6ae3a9bd9d593aff Mon Sep 17 00:00:00 2001
From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Date: Fri, 13 May 2016 11:43:41 +0200
Subject: [PATCH 10/12] Remove root pixmap destroy from ARMSOCCloseScreen()
Calling DestroyPixmap() on devPrivate triggers an
assertion in the server.
X: xorg-server-1.18.3/include/privates.h:122:
dixGetPrivateAddr: Assertion `key->initialized' failed.
---
src/armsoc_driver.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/src/armsoc_driver.c b/src/armsoc_driver.c
index a8cafe3..25c5198 100644
--- a/src/armsoc_driver.c
+++ b/src/armsoc_driver.c
@@ -1101,16 +1101,6 @@ ARMSOCCloseScreen(CLOSE_SCREEN_ARGS_DECL)
drmmode_screen_fini(pScrn);
drmmode_cursor_fini(pScreen);
- /* pScreen->devPrivate holds the root pixmap created around our bo by miCreateResources which is installed
- * by fbScreenInit() when called from ARMSOCScreenInit().
- * This pixmap should be destroyed in miScreenClose() but this isn't wrapped by fbScreenInit() so to prevent a leak
- * we do it here, before calling the CloseScreen chain which would just free pScreen->devPrivate in fbCloseScreen()
- */
- if (pScreen->devPrivate) {
- (void) (*pScreen->DestroyPixmap)(pScreen->devPrivate);
- pScreen->devPrivate = NULL;
- }
-
unwrap(pARMSOC, pScreen, CloseScreen);
unwrap(pARMSOC, pScreen, BlockHandler);
unwrap(pARMSOC, pScreen, CreateScreenResources);
--
2.20.1
From c97ff6d3974feb373a3c04091f33f68f157a1bc0 Mon Sep 17 00:00:00 2001
From: Jonathan Bakker <xc-racer2@live.ca>
Date: Sat, 15 Feb 2020 14:57:19 -0800
Subject: [PATCH 11/12] Add EXA using the Samsung G2D
Heavily based on/inspired by
https://github.com/tobiasjakobi/xf86-video-armsoc
https://github.com/OtherCrashOverride/xf86-video-armsoc
Currently only Solid and Copy are accelerated and only for non-userptr
buffers.
Appears to occasionally have some issues with g2d_copy
---
configure.ac | 1 +
src/Makefile.am | 1 +
src/armsoc_driver.c | 8 +
src/armsoc_exa.h | 5 +
src/armsoc_exa_g2d.c | 384 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 399 insertions(+)
create mode 100644 src/armsoc_exa_g2d.c
diff --git a/configure.ac b/configure.ac
index 060279f..a4fa4ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ PKG_CHECK_MODULES(XORG,
xproto
fontsproto
libdrm
+ libdrm_exynos
dri2proto
pixman-1
$REQUIRED_MODULES)
diff --git a/src/Makefile.am b/src/Makefile.am
index 3b26019..0a44fdf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,6 +49,7 @@ DRMMODE_SRCS = drmmode_exynos/drmmode_exynos.c \
armsoc_drv_la_SOURCES = \
drmmode_display.c \
armsoc_exa.c \
+ armsoc_exa_g2d.c \
armsoc_exa_null.c \
armsoc_dri2.c \
armsoc_driver.c \
diff --git a/src/armsoc_driver.c b/src/armsoc_driver.c
index 25c5198..71d6d27 100644
--- a/src/armsoc_driver.c
+++ b/src/armsoc_driver.c
@@ -818,6 +818,14 @@ ARMSOCAccelInit(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
+ /*
+ * Try to initialize G2D accelerated EXA first. If that fails
+ * use the non-accelerated EXA fallback.
+ */
+ if (!pARMSOC->pARMSOCEXA)
+ pARMSOC->pARMSOCEXA = InitExynosG2DEXA(pScreen, pScrn,
+ pARMSOC->drmFD);
+
if (!pARMSOC->pARMSOCEXA)
pARMSOC->pARMSOCEXA = InitNullEXA(pScreen, pScrn,
pARMSOC->drmFD);
diff --git a/src/armsoc_exa.h b/src/armsoc_exa.h
index 1eab09f..603a3b4 100644
--- a/src/armsoc_exa.h
+++ b/src/armsoc_exa.h
@@ -65,6 +65,11 @@ struct ARMSOCEXARec {
};
+/**
+ * Exynos G2D EXA implementation
+ */
+struct ARMSOCEXARec *InitExynosG2DEXA(ScreenPtr pScreen, ScrnInfoPtr pScrn, int fd);
+
/**
* Fallback EXA implementation
*/
diff --git a/src/armsoc_exa_g2d.c b/src/armsoc_exa_g2d.c
new file mode 100644
index 0000000..baac7f1
--- /dev/null
+++ b/src/armsoc_exa_g2d.c
@@ -0,0 +1,384 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, 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:
+ * Rob Clark <rob@ti.com>
+ */
+
+#include <libdrm/exynos_drmif.h>
+#include <exynos/exynos_fimg2d.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "armsoc_driver.h"
+#include "armsoc_exa.h"
+
+#include "exa.h"
+
+/**
+ * This file has an EXA implementation which accelerates solid fill and copy
+ * operations on Samsung chipsets using the G2D IP present.
+ */
+
+enum g2d_copy_type {
+ G2D_COPY,
+ G2D_MOVE,
+};
+
+struct ARMSOCG2DEXARec {
+ struct ARMSOCEXARec base;
+ ExaDriverPtr exa;
+
+ struct g2d_context* ctx;
+
+ struct g2d_image dst;
+ struct g2d_image src;
+
+ enum g2d_copy_type copy_type;
+};
+
+static inline struct ARMSOCG2DEXARec *g2dEXARecFromPixmap(PixmapPtr pPixmap)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
+ struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
+ return (struct ARMSOCG2DEXARec*)(pARMSOC->pARMSOCEXA);
+}
+
+static unsigned int
+check_color_mode(PixmapPtr pPixmap, Pixel planemask)
+{
+ unsigned int color_mode;
+
+ switch (pPixmap->drawable.depth) {
+ case 32:
+ color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+ if ((planemask & 0xffffffff) != 0xffffffff)
+ return 0;
+ break;
+ case 24:
+ color_mode = G2D_COLOR_FMT_XRGB8888 | G2D_ORDER_AXRGB;
+ if ((planemask & 0x00ffffff) != 0x00ffffff)
+ return 0;
+ break;
+ case 16:
+ color_mode = G2D_COLOR_FMT_RGB565 | G2D_ORDER_AXRGB;
+ if ((planemask & 0x0000ffff) != 0x0000ffff)
+ return 0;
+ break;
+ case 8:
+ color_mode = G2D_COLOR_FMT_A8 | G2D_ORDER_AXRGB;
+ if ((planemask & 0x000000ff) != 0x000000ff)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ return color_mode;
+}
+
+static Bool
+PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fill_colour)
+{
+ struct ARMSOCG2DEXARec *g2dPriv = g2dEXARecFromPixmap(pPixmap);
+ struct ARMSOCPixmapPrivRec *pixPriv = exaGetPixmapDriverPrivate(pPixmap);
+ unsigned int color_mode;
+
+ if (!is_accel_pixmap(pixPriv))
+ return FALSE;
+
+ if (alu != GXcopy)
+ return FALSE;
+
+ color_mode = check_color_mode(pPixmap, planemask);
+ if (color_mode == 0)
+ return FALSE;
+
+ g2dPriv->dst.buf_type = G2D_IMGBUF_GEM;
+ g2dPriv->dst.bo[0] = armsoc_bo_handle(pixPriv->bo);
+ g2dPriv->dst.width = pPixmap->drawable.width;
+ g2dPriv->dst.height = pPixmap->drawable.height;
+ g2dPriv->dst.stride = exaGetPixmapPitch(pPixmap);
+ g2dPriv->dst.color_mode = color_mode;
+ g2dPriv->dst.color = fill_colour;
+
+ return TRUE;
+}
+
+static void
+Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
+ struct ARMSOCG2DEXARec *g2dPriv = g2dEXARecFromPixmap(pPixmap);
+ int ret;
+
+solid_fill:
+ ret = g2d_solid_fill(g2dPriv->ctx, &g2dPriv->dst,
+ x1, y1, x2 - x1, y2 - y1);
+ if (ret < 0) {
+ if (ret == -ENOSPC) {
+ INFO_MSG("No space for solid fill, running g2d_exec");
+ ret = g2d_exec(g2dPriv->ctx);
+ if (ret < 0)
+ ERROR_MSG("g2d_exec failed: %d", ret);
+ else
+ goto solid_fill;
+ } else {
+ ERROR_MSG("g2d_solid_fill failed: %d", ret);
+ }
+ }
+}
+
+static void
+DoneSolid(PixmapPtr pPixmap)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
+ struct ARMSOCG2DEXARec *g2dPriv = g2dEXARecFromPixmap(pPixmap);
+ int ret;
+
+ ret = g2d_exec(g2dPriv->ctx);
+ if (ret < 0)
+ ERROR_MSG("g2d_exec failed: %d", ret);
+}
+
+static Bool
+PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int xdir, int ydir,
+ int alu, Pixel planemask)
+{
+ struct ARMSOCPixmapPrivRec *privSrc = exaGetPixmapDriverPrivate(pSrc);
+ struct ARMSOCPixmapPrivRec *privDst = exaGetPixmapDriverPrivate(pDst);
+ struct ARMSOCG2DEXARec *g2dPriv = g2dEXARecFromPixmap(pSrc);
+ unsigned int src_color_mode, dst_color_mode;
+
+ if (!is_accel_pixmap(privSrc) || !is_accel_pixmap(privDst))
+ return FALSE;
+
+ if (alu != GXcopy)
+ return FALSE;
+
+ src_color_mode = check_color_mode(pSrc, planemask);
+ if (src_color_mode == 0)
+ return FALSE;
+
+ dst_color_mode = check_color_mode(pDst, planemask);
+ if (dst_color_mode == 0)
+ return FALSE;
+
+ g2dPriv->src.buf_type = G2D_IMGBUF_GEM;
+ g2dPriv->src.bo[0] = armsoc_bo_handle(privSrc->bo);
+ g2dPriv->src.width = armsoc_bo_width(privSrc->bo);
+ g2dPriv->src.height = armsoc_bo_height(privSrc->bo);
+ g2dPriv->src.stride = exaGetPixmapPitch(pSrc);
+ g2dPriv->src.color_mode = src_color_mode;
+
+ if (pSrc == pDst) {
+ g2dPriv->copy_type = G2D_MOVE;
+ } else {
+ g2dPriv->copy_type = G2D_COPY;
+
+ g2dPriv->dst.buf_type = G2D_IMGBUF_GEM;
+ g2dPriv->dst.bo[0] = armsoc_bo_handle(privDst->bo);
+ g2dPriv->dst.width = armsoc_bo_width(privDst->bo);
+ g2dPriv->dst.height = armsoc_bo_height(privDst->bo);
+ g2dPriv->dst.stride = exaGetPixmapPitch(pDst);
+ g2dPriv->dst.color_mode = dst_color_mode;
+ }
+
+ return TRUE;
+}
+
+static void Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
+ int width, int height)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
+ struct ARMSOCG2DEXARec *g2dPriv = g2dEXARecFromPixmap(pDstPixmap);
+ int ret;
+
+exec_op:
+ if (g2dPriv->copy_type == G2D_MOVE) {
+ ret = g2d_move(g2dPriv->ctx, &g2dPriv->src,
+ srcX, srcY, dstX, dstY, width, height);
+ } else {
+ ret = g2d_copy(g2dPriv->ctx, &g2dPriv->src, &g2dPriv->dst,
+ srcX, srcY, dstX, dstY, width, height);
+ }
+
+ if (ret < 0) {
+ if (ret == -ENOSPC) {
+ INFO_MSG("No space for %s, running g2d_exec",
+ g2dPriv->copy_type == G2D_MOVE ? "g2d_move" :
+ "g2d_copy");
+ ret = g2d_exec(g2dPriv->ctx);
+ if (ret < 0)
+ ERROR_MSG("g2d_exec failed: %d", ret);
+ else
+ goto exec_op;
+ } else {
+ ERROR_MSG("%s failed: %d",
+ g2dPriv->copy_type == G2D_MOVE ? "g2d_move" :
+ "g2d_copy", ret);
+ }
+ }
+}
+
+static void DoneCopy(PixmapPtr pDstPixmap)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
+ struct ARMSOCG2DEXARec *g2dPriv = g2dEXARecFromPixmap(pDstPixmap);
+ int ret;
+
+ ret = g2d_exec(g2dPriv->ctx);
+ if (ret < 0)
+ ERROR_MSG("g2d_exec failed: %d", ret);
+}
+
+static Bool
+CheckCompositeFail(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ return FALSE;
+}
+
+static Bool
+PrepareCompositeFail(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture, PixmapPtr pSrc,
+ PixmapPtr pMask, PixmapPtr pDst)
+{
+ return FALSE;
+}
+
+/**
+ * CloseScreen() is called at the end of each server generation and
+ * cleans up everything initialised in InitExynosG2DEXA()
+ */
+static Bool
+CloseScreen(CLOSE_SCREEN_ARGS_DECL)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
+ struct ARMSOCG2DEXARec *g2dPriv = (struct ARMSOCG2DEXARec *)pARMSOC->pARMSOCEXA;
+
+ exaDriverFini(pScreen);
+
+ g2d_fini(g2dPriv->ctx);
+
+ free(g2dPriv->exa);
+ free(pARMSOC->pARMSOCEXA);
+ pARMSOC->pARMSOCEXA = NULL;
+
+ return TRUE;
+}
+
+/* FreeScreen() is called on an error during PreInit and
+ * should clean up anything initialised before InitExynosG2DEXA()
+ * (which currently is nothing)
+ *
+ */
+static void
+FreeScreen(FREE_SCREEN_ARGS_DECL)
+{
+}
+
+struct ARMSOCEXARec *
+InitExynosG2DEXA(ScreenPtr pScreen, ScrnInfoPtr pScrn, int fd)
+{
+ struct ARMSOCG2DEXARec *g2d_exa;
+ struct ARMSOCEXARec *armsoc_exa;
+ ExaDriverPtr exa;
+
+ INFO_MSG("G2D EXA mode");
+
+ g2d_exa = calloc(1, sizeof(*g2d_exa));
+ if (!g2d_exa)
+ goto out;
+
+ g2d_exa->ctx = g2d_init(fd);
+ if (!g2d_exa->ctx) {
+ ERROR_MSG("g2d_init fail");
+ goto free_g2d_exa;
+ }
+
+ armsoc_exa = (struct ARMSOCEXARec *)g2d_exa;
+
+ exa = exaDriverAlloc();
+ if (!exa)
+ goto free_g2d;
+
+ g2d_exa->exa = exa;
+
+ exa->exa_major = EXA_VERSION_MAJOR;
+ exa->exa_minor = EXA_VERSION_MINOR;
+
+ exa->pixmapOffsetAlign = 0;
+ exa->pixmapPitchAlign = 32;
+ exa->flags = EXA_OFFSCREEN_PIXMAPS |
+ EXA_HANDLES_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX;
+ exa->maxX = 4096;
+ exa->maxY = 4096;
+
+ /* Required EXA functions: */
+ exa->WaitMarker = ARMSOCWaitMarker;
+ exa->CreatePixmap2 = ARMSOCCreatePixmap2;
+ exa->DestroyPixmap = ARMSOCDestroyPixmap;
+ exa->ModifyPixmapHeader = ARMSOCModifyPixmapHeader;
+
+ exa->PrepareAccess = ARMSOCPrepareAccess;
+ exa->FinishAccess = ARMSOCFinishAccess;
+ exa->PixmapIsOffscreen = ARMSOCPixmapIsOffscreen;
+
+ /* Accelerate solid fill */
+ exa->PrepareSolid = PrepareSolid;
+ exa->Solid = Solid;
+ exa->DoneSolid = DoneSolid;
+
+ /* Accelerate copy */
+ exa->PrepareCopy = PrepareCopy;
+ exa->Copy = Copy;
+ exa->DoneCopy = DoneCopy;
+
+ /* Always fallback for software operations */
+ exa->CheckComposite = CheckCompositeFail;
+ exa->PrepareComposite = PrepareCompositeFail;
+
+ if (!exaDriverInit(pScreen, exa)) {
+ ERROR_MSG("exaDriverInit failed");
+ goto free_exa;
+ }
+
+ armsoc_exa->CloseScreen = CloseScreen;
+ armsoc_exa->FreeScreen = FreeScreen;
+
+ return armsoc_exa;
+
+free_exa:
+ free(exa);
+free_g2d:
+ g2d_fini(g2d_exa->ctx);
+free_g2d_exa:
+ free(g2d_exa);
+out:
+ return NULL;
+}
--
2.20.1
From 2643a94a21c1a954eb2dc0852e4ab2392abf952d Mon Sep 17 00:00:00 2001
From: Jonathan Bakker <xc-racer2@live.ca>
Date: Sat, 15 Feb 2020 16:28:37 -0800
Subject: [PATCH 12/12] Set the prefix to /usr
Debian for one installs the xorg modules to here
---
autogen.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/autogen.sh b/autogen.sh
index 2ca7e5d..aa17d6e 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -22,7 +22,7 @@ test -n "$NOCONFIGURE" && {
exit 0
}
-CONFIGURE_DEF_OPT="--enable-maintainer-mode"
+CONFIGURE_DEF_OPT="--enable-maintainer-mode --prefix=/usr"
echo ./configure $CONFIGURE_DEF_OPT $*
./configure $CONFIGURE_DEF_OPT $* || {
echo " configure failed"
--
2.20.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment