├── .gitignore ├── COPYING ├── Makefile.am ├── README ├── autogen.sh ├── configure.ac └── src ├── Makefile.am ├── compat-api.h ├── display.c ├── driver.c ├── driver.h ├── glutils.c ├── hwcomposer.c ├── present.c ├── renderer.c └── shaders.c /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # X.Org module default exclusion patterns 3 | # The next section if for module specific patterns 4 | # 5 | # Do not edit the following section 6 | # GNU Build System (Autotools) 7 | aclocal.m4 8 | autom4te.cache/ 9 | autoscan.log 10 | ChangeLog 11 | compile 12 | config.guess 13 | config.h 14 | config.h.in 15 | config.log 16 | config-ml.in 17 | config.py 18 | config.status 19 | config.status.lineno 20 | config.sub 21 | configure 22 | configure.scan 23 | depcomp 24 | .deps/ 25 | INSTALL 26 | install-sh 27 | .libs/ 28 | libtool 29 | libtool.m4 30 | ltmain.sh 31 | lt~obsolete.m4 32 | ltoptions.m4 33 | ltsugar.m4 34 | ltversion.m4 35 | Makefile 36 | Makefile.in 37 | mdate-sh 38 | missing 39 | mkinstalldirs 40 | *.pc 41 | py-compile 42 | stamp-h? 43 | symlink-tree 44 | texinfo.tex 45 | ylwrap 46 | 47 | # Do not edit the following section 48 | # Edit Compile Debug Document Distribute 49 | *~ 50 | *.[0-9] 51 | *.[0-9]x 52 | *.bak 53 | *.bin 54 | core 55 | *.dll 56 | *.exe 57 | *-ISO*.bdf 58 | *-JIS*.bdf 59 | *-KOI8*.bdf 60 | *.kld 61 | *.ko 62 | *.ko.cmd 63 | *.lai 64 | *.l[oa] 65 | *.[oa] 66 | *.obj 67 | *.patch 68 | *.so 69 | *.pcf.gz 70 | *.pdb 71 | *.tar.bz2 72 | *.tar.gz 73 | # 74 | # Add & Override patterns for xf86-video-dummy 75 | # 76 | # Edit the following section as needed 77 | # For example, !report.pc overrides *.pc. See 'man gitignore' 78 | # 79 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2002, SuSE Linux AG, Author: Egbert Eich 2 | 3 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright 2005 Adam Jackson. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # on the rights to use, copy, modify, merge, publish, distribute, sub 7 | # license, and/or sell copies of the Software, and to permit persons to whom 8 | # the Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 | # ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | SUBDIRS = src 22 | MAINTAINERCLEANFILES = ChangeLog 23 | 24 | .PHONY: ChangeLog 25 | 26 | ChangeLog: 27 | $(CHANGELOG_CMD) 28 | 29 | dist-hook: ChangeLog 30 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | xf86-video-hwcomposer - frame buffer driver for the Xorg X server, 2 | utilizing Android HWComposer API through libhybris for rendering. 3 | 4 | It's heavily based on xf86-video-dummy with HWComposer API calls and 5 | rendering through OpenGL ES2 added. 6 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | srcdir=`dirname "$0"` 4 | test -z "$srcdir" && srcdir=. 5 | 6 | ORIGDIR=`pwd` 7 | cd "$srcdir" 8 | 9 | autoreconf -v --install || exit 1 10 | cd "$ORIGDIR" || exit $? 11 | 12 | git config --local --get format.subjectPrefix >/dev/null 2>&1 || 13 | git config --local format.subjectPrefix "PATCH xf86-video-dummy" 14 | 15 | if test -z "$NOCONFIGURE"; then 16 | exec "$srcdir"/configure "$@" 17 | fi 18 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # Copyright 2005 Adam Jackson. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # on the rights to use, copy, modify, merge, publish, distribute, sub 7 | # license, and/or sell copies of the Software, and to permit persons to whom 8 | # the Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 | # ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | # 21 | # Process this file with autoconf to produce a configure script 22 | 23 | # Initialize Autoconf 24 | AC_PREREQ([2.60]) 25 | AC_INIT([xf86-video-hwcomposer], 26 | [0.3.8], 27 | [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], 28 | [xf86-video-hwcomposer]) 29 | AC_CONFIG_SRCDIR([Makefile.am]) 30 | AC_CONFIG_HEADERS([config.h]) 31 | AC_CONFIG_AUX_DIR(.) 32 | 33 | # Initialize Automake 34 | AM_INIT_AUTOMAKE([foreign dist-bzip2]) 35 | 36 | # Require xorg-macros: XORG_DEFAULT_OPTIONS 37 | m4_ifndef([XORG_MACROS_VERSION], 38 | [m4_fatal([must install xorg-macros 1.3 or later before running autoconf/autogen])]) 39 | XORG_MACROS_VERSION(1.3) 40 | XORG_DEFAULT_OPTIONS 41 | 42 | # Initialize libtool 43 | AC_DISABLE_STATIC 44 | AC_PROG_LIBTOOL 45 | 46 | AH_TOP([#include "xorg-server.h"]) 47 | 48 | # Define a configure option for an alternate module directory 49 | AC_ARG_WITH(xorg-module-dir, 50 | AS_HELP_STRING([--with-xorg-module-dir=DIR], 51 | [Default xorg module directory [[default=$libdir/xorg/modules]]]), 52 | [moduledir="$withval"], 53 | [moduledir="$libdir/xorg/modules"]) 54 | AC_SUBST(moduledir) 55 | 56 | # Store the list of server defined optional extensions in REQUIRED_MODULES 57 | XORG_DRIVER_CHECK_EXT(RANDR, randrproto) 58 | XORG_DRIVER_CHECK_EXT(RENDER, renderproto) 59 | 60 | # Obtain compiler/linker options for the driver dependencies 61 | PKG_CHECK_MODULES(XORG, [xorg-server >= 1.4.99.901] xproto fontsproto $REQUIRED_MODULES) 62 | 63 | # Checks for libraries. 64 | 65 | AC_CHECK_HEADER([hardware/hardware.h], [have_libhardware=yes], [have_libhardware=no]) 66 | 67 | if test "x$have_libhardware" = xyes; then 68 | LIBS="$LIBS -lhardware -lsync -lhybris-hwcomposerwindow -lEGL -lGLESv2" 69 | AC_DEFINE(HAVE_LIBHARDWARE,[1],[libhardware library]) 70 | fi 71 | 72 | AM_CONDITIONAL([HAVE_LIBHARDWARE], [test x$have_libhardware = xyes]) 73 | 74 | AC_ARG_ENABLE([drihybris], 75 | AS_HELP_STRING([--enable-drihybris], [Enable DRIHYBRIS support])) 76 | 77 | if test "x$enable_drihybris" = xyes; then 78 | AC_DEFINE(ENABLE_DRIHYBRIS,[1],[Enable DRIHYBRIS driver support]) 79 | fi 80 | 81 | AM_CONDITIONAL([ENABLE_DRIHYBRIS], [test x$enable_drihybris = xyes]) 82 | 83 | AC_ARG_ENABLE([glamor-hybris], 84 | AS_HELP_STRING([--enable-glamor-hybris], [Enable experimental glamor support (requires modified glamor-hybris)])) 85 | 86 | AS_IF([test "x$enable_glamor_hybris" = "xyes"], [ 87 | AC_DEFINE(ENABLE_GLAMOR,[1],[enable glamor support]) 88 | ]) 89 | 90 | AM_CONDITIONAL([ENABLE_GLAMOR], [test x$enable_glamor = xyes]) 91 | 92 | DRIVER_NAME=hwcomposer 93 | AC_SUBST([DRIVER_NAME]) 94 | 95 | AC_CONFIG_FILES([ 96 | Makefile 97 | src/Makefile 98 | ]) 99 | AC_OUTPUT 100 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright 2005 Adam Jackson. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # on the rights to use, copy, modify, merge, publish, distribute, sub 7 | # license, and/or sell copies of the Software, and to permit persons to whom 8 | # the Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 | # ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | # this is obnoxious: 23 | # -module lets us name the module exactly how we want 24 | # -avoid-version prevents gratuitous .0.0.0 version numbers on the end 25 | # _ladir passes a dummy rpath to libtool so the thing will actually link 26 | # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. 27 | 28 | AM_CFLAGS = $(XORG_CFLAGS) 29 | 30 | hwcomposer_drv_la_LTLIBRARIES = hwcomposer_drv.la 31 | hwcomposer_drv_la_LDFLAGS = -module -avoid-version -lhardware -lsync -lepoxy 32 | hwcomposer_drv_la_LIBADD = $(XORG_LIBS) 33 | hwcomposer_drv_ladir = @moduledir@/drivers 34 | 35 | hwcomposer_drv_la_SOURCES = \ 36 | compat-api.h \ 37 | display.c \ 38 | driver.c \ 39 | driver.h \ 40 | glutils.c \ 41 | hwcomposer.c \ 42 | present.c \ 43 | renderer.c \ 44 | shaders.c 45 | -------------------------------------------------------------------------------- /src/compat-api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Red Hat, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | * Author: Dave Airlie 24 | */ 25 | 26 | /* this file provides API compat between server post 1.13 and pre it, 27 | it should be reused inside as many drivers as possible */ 28 | #ifndef COMPAT_API_H 29 | #define COMPAT_API_H 30 | 31 | #ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR 32 | #define GetGlyphPicture(g, s) GlyphPicture((g))[(s)->myNum] 33 | #define SetGlyphPicture(g, s, p) GlyphPicture((g))[(s)->myNum] = p 34 | #endif 35 | 36 | #ifndef XF86_HAS_SCRN_CONV 37 | #define xf86ScreenToScrn(s) xf86Screens[(s)->myNum] 38 | #define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex] 39 | #endif 40 | 41 | #ifndef XF86_SCRN_INTERFACE 42 | 43 | #define SCRN_ARG_TYPE int 44 | #define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = xf86Screens[(arg1)] 45 | 46 | #define SCREEN_ARG_TYPE int 47 | #define SCREEN_PTR(arg1) ScreenPtr pScreen = screenInfo.screens[(arg1)] 48 | 49 | #define SCREEN_INIT_ARGS_DECL int i, ScreenPtr pScreen, int argc, char **argv 50 | 51 | #define BLOCKHANDLER_ARGS_DECL int arg, pointer blockData, pointer pTimeout, pointer pReadmask 52 | #define BLOCKHANDLER_ARGS arg, blockData, pTimeout, pReadmask 53 | 54 | #define CLOSE_SCREEN_ARGS_DECL int scrnIndex, ScreenPtr pScreen 55 | #define CLOSE_SCREEN_ARGS scrnIndex, pScreen 56 | 57 | #define ADJUST_FRAME_ARGS_DECL int arg, int x, int y, int flags 58 | #define ADJUST_FRAME_ARGS(arg, x, y) (arg)->scrnIndex, x, y, 0 59 | 60 | #define SWITCH_MODE_ARGS_DECL int arg, DisplayModePtr mode, int flags 61 | #define SWITCH_MODE_ARGS(arg, m) (arg)->scrnIndex, m, 0 62 | 63 | #define FREE_SCREEN_ARGS_DECL int arg, int flags 64 | #define FREE_SCREEN_ARGS(x) (x)->scrnIndex, 0 65 | 66 | #define VT_FUNC_ARGS_DECL int arg, int flags 67 | #define VT_FUNC_ARGS(flags) pScrn->scrnIndex, (flags) 68 | 69 | #define XF86_ENABLEDISABLEFB_ARG(x) ((x)->scrnIndex) 70 | #else 71 | #define SCRN_ARG_TYPE ScrnInfoPtr 72 | #define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = (arg1) 73 | 74 | #define SCREEN_ARG_TYPE ScreenPtr 75 | #define SCREEN_PTR(arg1) ScreenPtr pScreen = (arg1) 76 | 77 | #define SCREEN_INIT_ARGS_DECL ScreenPtr pScreen, int argc, char **argv 78 | 79 | #define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask 80 | #define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask 81 | 82 | #define CLOSE_SCREEN_ARGS_DECL ScreenPtr pScreen 83 | #define CLOSE_SCREEN_ARGS pScreen 84 | 85 | #define ADJUST_FRAME_ARGS_DECL ScrnInfoPtr arg, int x, int y 86 | #define ADJUST_FRAME_ARGS(arg, x, y) arg, x, y 87 | 88 | #define SWITCH_MODE_ARGS_DECL ScrnInfoPtr arg, DisplayModePtr mode 89 | #define SWITCH_MODE_ARGS(arg, m) arg, m 90 | 91 | #define FREE_SCREEN_ARGS_DECL ScrnInfoPtr arg 92 | #define FREE_SCREEN_ARGS(x) (x) 93 | 94 | #define VT_FUNC_ARGS_DECL ScrnInfoPtr arg 95 | #define VT_FUNC_ARGS(flags) pScrn 96 | 97 | #define XF86_ENABLEDISABLEFB_ARG(x) (x) 98 | 99 | #endif 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/display.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include "config.h" 3 | #endif 4 | 5 | #include 6 | #include "xf86Crtc.h" 7 | 8 | #include "driver.h" 9 | 10 | Bool hwc_lights_init(ScrnInfoPtr pScrn) 11 | { 12 | HWCPtr hwc = HWCPTR(pScrn); 13 | hwc->lightsDevice = NULL; 14 | hw_module_t *lightsModule = NULL; 15 | struct light_device_t *lightsDevice = NULL; 16 | 17 | /* Use 255 as default */ 18 | hwc->screenBrightness = 255; 19 | 20 | if (hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (const hw_module_t **)&lightsModule) != 0) { 21 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to get lights module\n"); 22 | return FALSE; 23 | } 24 | 25 | if (lightsModule->methods->open(lightsModule, LIGHT_ID_BACKLIGHT, (hw_device_t **)&lightsDevice) != 0) { 26 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to create lights device\n"); 27 | return FALSE; 28 | } 29 | 30 | hwc->lightsDevice = lightsDevice; 31 | return TRUE; 32 | } 33 | 34 | static Bool 35 | hwc_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height) 36 | { 37 | ScreenPtr pScreen = pScrn->pScreen; 38 | 39 | if (pScrn->virtualX == width && pScrn->virtualY == height) 40 | return TRUE; 41 | 42 | /* We don't support real resizing yet */ 43 | return FALSE; 44 | } 45 | 46 | static const xf86CrtcConfigFuncsRec hwc_xf86crtc_config_funcs = { 47 | hwc_xf86crtc_resize 48 | }; 49 | 50 | static void hwcomposer_crtc_dpms(xf86CrtcPtr crtc, int mode) 51 | { 52 | } 53 | 54 | static Bool hwcomposer_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y) 55 | { 56 | crtc->mode = *mode; 57 | crtc->x = x; 58 | crtc->y = y; 59 | crtc->rotation = rotation; 60 | 61 | return TRUE; 62 | } 63 | 64 | static void 65 | hwc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) 66 | { 67 | 68 | } 69 | 70 | static void 71 | hwc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) 72 | { 73 | HWCPtr hwc = HWCPTR(crtc->scrn); 74 | hwc->cursorX = x; 75 | hwc->cursorY = y; 76 | hwc->dirty = TRUE; 77 | } 78 | 79 | /* 80 | * The load_cursor_argb_check driver hook. 81 | * 82 | * Sets the hardware cursor by uploading it to texture. 83 | * On failure, returns FALSE indicating that the X server should fall 84 | * back to software cursors. 85 | */ 86 | static Bool 87 | hwc_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image) 88 | { 89 | HWCPtr hwc = HWCPTR(crtc->scrn); 90 | 91 | glBindTexture(GL_TEXTURE_2D, hwc->renderer.cursorTexture); 92 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 93 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 94 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, hwc->cursorWidth, hwc->cursorHeight, 95 | 0, GL_RGBA, GL_UNSIGNED_BYTE, image); 96 | 97 | hwc->dirty = TRUE; 98 | return TRUE; 99 | } 100 | 101 | static void 102 | hwc_hide_cursor(xf86CrtcPtr crtc) 103 | { 104 | HWCPtr hwc = HWCPTR(crtc->scrn); 105 | hwc->cursorShown = FALSE; 106 | hwc->dirty = TRUE; 107 | } 108 | 109 | static void 110 | hwc_show_cursor(xf86CrtcPtr crtc) 111 | { 112 | HWCPtr hwc = HWCPTR(crtc->scrn); 113 | hwc->cursorShown = TRUE; 114 | hwc->dirty = TRUE; 115 | } 116 | 117 | static const xf86CrtcFuncsRec hwcomposer_crtc_funcs = { 118 | .dpms = hwcomposer_crtc_dpms, 119 | .set_mode_major = hwcomposer_set_mode_major, 120 | .set_cursor_colors = hwc_set_cursor_colors, 121 | .set_cursor_position = hwc_set_cursor_position, 122 | .show_cursor = hwc_show_cursor, 123 | .hide_cursor = hwc_hide_cursor, 124 | .load_cursor_argb_check = hwc_load_cursor_argb_check 125 | }; 126 | 127 | static void 128 | hwc_output_dpms(xf86OutputPtr output, int mode) 129 | { 130 | ScrnInfoPtr pScrn; 131 | pScrn = output->scrn; 132 | HWCPtr hwc = HWCPTR(pScrn); 133 | 134 | hwc->dpmsMode = mode; 135 | hwc_toggle_screen_brightness(pScrn); 136 | 137 | hwc_set_power_mode(pScrn, HWC_DISPLAY_PRIMARY, (mode == DPMSModeOn) ? 1 : 0); 138 | 139 | if (mode == DPMSModeOn) 140 | // Force redraw after unblank 141 | hwc->dirty = TRUE; 142 | } 143 | 144 | static xf86OutputStatus 145 | hwc_output_detect(xf86OutputPtr output) 146 | { 147 | return XF86OutputStatusConnected; 148 | } 149 | 150 | static int 151 | hwc_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 152 | { 153 | return MODE_OK; 154 | } 155 | 156 | static DisplayModePtr 157 | hwc_output_get_modes(xf86OutputPtr output) 158 | { 159 | ScrnInfoPtr pScrn; 160 | pScrn = output->scrn; 161 | HWCPtr hwc = HWCPTR(pScrn); 162 | 163 | return xf86DuplicateModes(NULL, hwc->modes); 164 | } 165 | 166 | static const xf86OutputFuncsRec hwc_output_funcs = { 167 | .dpms = hwc_output_dpms, 168 | .detect = hwc_output_detect, 169 | .mode_valid = hwc_output_mode_valid, 170 | .get_modes = hwc_output_get_modes 171 | }; 172 | 173 | Bool 174 | hwc_display_pre_init(ScrnInfoPtr pScrn) 175 | { 176 | HWCPtr hwc = HWCPTR(pScrn); 177 | xf86OutputPtr output; 178 | xf86CrtcPtr crtc; 179 | 180 | /* Pick up size from the "Display" subsection if it exists */ 181 | if (pScrn->display->virtualX) { 182 | pScrn->virtualX = pScrn->display->virtualX; 183 | pScrn->virtualY = pScrn->display->virtualY; 184 | } else { 185 | /* Pick rotated HWComposer screen resolution */ 186 | if (hwc->rotation == HWC_ROTATE_CW || hwc->rotation == HWC_ROTATE_CCW) { 187 | /* landscape mode on portrait panel: swap x/y */ 188 | pScrn->virtualX = hwc->hwcHeight; 189 | pScrn->virtualY = hwc->hwcWidth; 190 | } else { 191 | pScrn->virtualX = hwc->hwcWidth; 192 | pScrn->virtualY = hwc->hwcHeight; 193 | } 194 | } 195 | pScrn->displayWidth = pScrn->virtualX; 196 | 197 | /* Construct a mode with the screen's initial dimensions */ 198 | hwc->modes = xf86CVTMode(pScrn->virtualX, pScrn->virtualY, 60, 0, 0); 199 | 200 | xf86CrtcConfigInit(pScrn, &hwc_xf86crtc_config_funcs); 201 | xf86CrtcSetSizeRange(pScrn, 8, 8, SHRT_MAX, SHRT_MAX); 202 | 203 | output = xf86OutputCreate(pScrn, &hwc_output_funcs, "hwcomposer"); 204 | output->possible_crtcs = 0x7f; 205 | 206 | crtc = xf86CrtcCreate(pScrn, &hwcomposer_crtc_funcs); 207 | 208 | xf86ProviderSetup(pScrn, NULL, "hwcomposer"); 209 | 210 | xf86InitialConfiguration(pScrn, TRUE); 211 | 212 | pScrn->currentMode = pScrn->modes; 213 | crtc->funcs->set_mode_major(crtc, pScrn->currentMode, RR_Rotate_0, 0, 0); 214 | 215 | return TRUE; 216 | } 217 | -------------------------------------------------------------------------------- /src/driver.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright 2002, SuSE Linux AG, Author: Egbert Eich 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | #include "config.h" 8 | #endif 9 | 10 | /* All drivers should typically include these */ 11 | #include "xf86.h" 12 | #include "xf86_OSproc.h" 13 | 14 | /* All drivers initialising the SW cursor need this */ 15 | #include "mipointer.h" 16 | 17 | /* All drivers using the mi colormap manipulation need this */ 18 | #include "micmap.h" 19 | 20 | /* identifying atom needed by magnifiers */ 21 | #include 22 | #include "property.h" 23 | 24 | #include "xf86cmap.h" 25 | #include "xf86Crtc.h" 26 | 27 | #include "fb.h" 28 | 29 | #include "picturestr.h" 30 | 31 | /* 32 | * Driver data structures. 33 | */ 34 | #include "driver.h" 35 | 36 | #ifdef ENABLE_GLAMOR 37 | #define GLAMOR_FOR_XORG 1 38 | #include 39 | #endif 40 | #ifdef ENABLE_DRIHYBRIS 41 | #include 42 | #endif 43 | 44 | /* These need to be checked */ 45 | #include 46 | #include 47 | #include "scrnintstr.h" 48 | #include "servermd.h" 49 | 50 | /* Mandatory functions */ 51 | static const OptionInfoRec * AvailableOptions(int chipid, int busid); 52 | static void Identify(int flags); 53 | static Bool Probe(DriverPtr drv, int flags); 54 | static Bool PreInit(ScrnInfoPtr pScrn, int flags); 55 | static Bool ScreenInit(SCREEN_INIT_ARGS_DECL); 56 | static Bool EnterVT(VT_FUNC_ARGS_DECL); 57 | static void LeaveVT(VT_FUNC_ARGS_DECL); 58 | static Bool CloseScreen(CLOSE_SCREEN_ARGS_DECL); 59 | static void FreeScreen(FREE_SCREEN_ARGS_DECL); 60 | static ModeStatus ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 61 | Bool verbose, int flags); 62 | static Bool SaveScreen(ScreenPtr pScreen, int mode); 63 | 64 | /* Internally used functions */ 65 | static Bool hwc_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, 66 | pointer ptr); 67 | 68 | #define HWC_VERSION 1 69 | #define HWC_NAME "hwcomposer" 70 | #define HWC_DRIVER_NAME "hwcomposer" 71 | 72 | #define HWC_MAJOR_VERSION PACKAGE_VERSION_MAJOR 73 | #define HWC_MINOR_VERSION PACKAGE_VERSION_MINOR 74 | #define HWC_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 75 | 76 | // For ~60 FPS 77 | #define TIMER_DELAY 17 /* in milliseconds */ 78 | 79 | /* 80 | * This is intentionally screen-independent. It indicates the binding 81 | * choice made in the first PreInit. 82 | */ 83 | static int pix24bpp = 0; 84 | 85 | /* 86 | * This contains the functions needed by the server after loading the driver 87 | * module. It must be supplied, and gets passed back by the SetupProc 88 | * function in the dynamic case. In the static case, a reference to this 89 | * is compiled in, and this requires that the name of this DriverRec be 90 | * an upper-case version of the driver name. 91 | */ 92 | 93 | _X_EXPORT DriverRec hwcomposer = { 94 | HWC_VERSION, 95 | HWC_DRIVER_NAME, 96 | Identify, 97 | Probe, 98 | AvailableOptions, 99 | NULL, 100 | 0, 101 | hwc_driver_func 102 | }; 103 | 104 | static SymTabRec Chipsets[] = { 105 | { 0, "hwcomposer" }, 106 | { -1, NULL } 107 | }; 108 | 109 | typedef enum { 110 | OPTION_ACCEL_METHOD, 111 | OPTION_EGL_PLATFORM, 112 | OPTION_SW_CURSOR, 113 | OPTION_ROTATE 114 | } Opts; 115 | 116 | static const OptionInfoRec Options[] = { 117 | { OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, 118 | { OPTION_EGL_PLATFORM, "EGLPlatform", OPTV_STRING, {0}, FALSE}, 119 | { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN,{0}, FALSE}, 120 | { OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, 121 | { -1, NULL, OPTV_NONE, {0}, FALSE } 122 | }; 123 | 124 | #ifdef XFree86LOADER 125 | 126 | static MODULESETUPPROTO(Setup); 127 | 128 | static XF86ModuleVersionInfo hwcomposerVersRec = 129 | { 130 | "hwcomposer", 131 | MODULEVENDORSTRING, 132 | MODINFOSTRING1, 133 | MODINFOSTRING2, 134 | XORG_VERSION_CURRENT, 135 | HWC_MAJOR_VERSION, HWC_MINOR_VERSION, HWC_PATCHLEVEL, 136 | ABI_CLASS_VIDEODRV, 137 | ABI_VIDEODRV_VERSION, 138 | MOD_CLASS_VIDEODRV, 139 | {0,0,0,0} 140 | }; 141 | 142 | /* 143 | * This is the module init data. 144 | * Its name has to be the driver name followed by ModuleData 145 | */ 146 | _X_EXPORT XF86ModuleData hwcomposerModuleData = { &hwcomposerVersRec, Setup, NULL }; 147 | 148 | static pointer 149 | Setup(pointer module, pointer opts, int *errmaj, int *errmin) 150 | { 151 | static Bool setupDone = FALSE; 152 | 153 | if (!setupDone) { 154 | setupDone = TRUE; 155 | xf86AddDriver(&hwcomposer, module, HaveDriverFuncs); 156 | 157 | /* 158 | * Modules that this driver always requires can be loaded here 159 | * by calling LoadSubModule(). 160 | */ 161 | 162 | /* 163 | * The return value must be non-NULL on success even though there 164 | * is no TearDownProc. 165 | */ 166 | return (pointer)1; 167 | } else { 168 | if (errmaj) *errmaj = LDR_ONCEONLY; 169 | return NULL; 170 | } 171 | } 172 | 173 | #endif /* XFree86LOADER */ 174 | 175 | /* 176 | * Build a DisplayModeRec that matches the screen's dimensions. 177 | * 178 | * Make up a fake pixel clock so that applications that use the VidMode 179 | * extension to query the "refresh rate" get 60 Hz. 180 | */ 181 | static void ConstructFakeDisplayMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 182 | { 183 | mode->HDisplay = mode->HSyncStart = mode->HSyncEnd = mode->HTotal = 184 | pScrn->virtualX; 185 | mode->VDisplay = mode->VSyncStart = mode->VSyncEnd = mode->VTotal = 186 | pScrn->virtualY; 187 | mode->Clock = mode->HTotal * mode->VTotal * 60 / 1000; 188 | 189 | xf86SetCrtcForModes(pScrn, 0); 190 | } 191 | 192 | static Bool 193 | GetRec(ScrnInfoPtr pScrn) 194 | { 195 | /* 196 | * Allocate a HWCRec, and hook it into pScrn->driverPrivate. 197 | * pScrn->driverPrivate is initialised to NULL, so we can check if 198 | * the allocation has already been done. 199 | */ 200 | if (pScrn->driverPrivate != NULL) 201 | return TRUE; 202 | 203 | pScrn->driverPrivate = xnfcalloc(sizeof(HWCRec), 1); 204 | 205 | if (pScrn->driverPrivate == NULL) 206 | return FALSE; 207 | return TRUE; 208 | } 209 | 210 | static void 211 | FreeRec(ScrnInfoPtr pScrn) 212 | { 213 | if (pScrn->driverPrivate == NULL) 214 | return; 215 | free(pScrn->driverPrivate); 216 | pScrn->driverPrivate = NULL; 217 | } 218 | 219 | static const OptionInfoRec * 220 | AvailableOptions(int chipid, int busid) 221 | { 222 | return Options; 223 | } 224 | 225 | /* Mandatory */ 226 | static void 227 | Identify(int flags) 228 | { 229 | xf86PrintChipsets(HWC_NAME, "Driver for Android devices with HWComposser API", 230 | Chipsets); 231 | } 232 | 233 | /* Mandatory */ 234 | static Bool 235 | Probe(DriverPtr drv, int flags) 236 | { 237 | Bool foundScreen = FALSE; 238 | int numDevSections, numUsed; 239 | GDevPtr *devSections; 240 | int i; 241 | 242 | if (flags & PROBE_DETECT) 243 | return FALSE; 244 | /* 245 | * Find the config file Device sections that match this 246 | * driver, and return if there are none. 247 | */ 248 | if ((numDevSections = xf86MatchDevice(HWC_DRIVER_NAME, 249 | &devSections)) <= 0) { 250 | return FALSE; 251 | } 252 | 253 | numUsed = numDevSections; 254 | 255 | if (numUsed > 0) { 256 | for (i = 0; i < numUsed; i++) { 257 | ScrnInfoPtr pScrn = NULL; 258 | int entityIndex = 259 | xf86ClaimNoSlot(drv, 0, devSections[i], TRUE); 260 | /* Allocate a ScrnInfoRec and claim the slot */ 261 | if ((pScrn = xf86AllocateScreen(drv, 0))) { 262 | xf86AddEntityToScreen(pScrn,entityIndex); 263 | pScrn->driverVersion = HWC_VERSION; 264 | pScrn->driverName = HWC_DRIVER_NAME; 265 | pScrn->name = HWC_NAME; 266 | pScrn->Probe = Probe; 267 | pScrn->PreInit = PreInit; 268 | pScrn->ScreenInit = ScreenInit; 269 | pScrn->SwitchMode = SwitchMode; 270 | pScrn->AdjustFrame = AdjustFrame; 271 | pScrn->EnterVT = EnterVT; 272 | pScrn->LeaveVT = LeaveVT; 273 | pScrn->FreeScreen = FreeScreen; 274 | pScrn->ValidMode = ValidMode; 275 | 276 | foundScreen = TRUE; 277 | } 278 | } 279 | } 280 | 281 | free(devSections); 282 | 283 | return foundScreen; 284 | } 285 | 286 | #ifdef ENABLE_GLAMOR 287 | static void 288 | try_enable_glamor(ScrnInfoPtr pScrn) 289 | { 290 | HWCPtr hwc = HWCPTR(pScrn); 291 | const char *accel_method_str = xf86GetOptValString(hwc->Options, 292 | OPTION_ACCEL_METHOD); 293 | Bool do_glamor = (!accel_method_str || 294 | strcmp(accel_method_str, "glamor") == 0); 295 | 296 | if (!do_glamor) { 297 | xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n"); 298 | return; 299 | } 300 | 301 | #ifdef ENABLE_DRIHYBRIS 302 | #ifndef __ANDROID__ 303 | if (xf86LoadSubModule(pScrn, "drihybris")) 304 | #endif 305 | { 306 | hwc->drihybris = TRUE; 307 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, "drihybris initialized\n"); 308 | } 309 | #endif 310 | 311 | #ifndef __ANDROID__ 312 | if (xf86LoadSubModule(pScrn, GLAMOR_EGLHYBRIS_MODULE_NAME)) { 313 | #endif // __ANDROID__ 314 | if (hwc_glamor_egl_init(pScrn, hwc->renderer.display, 315 | hwc->renderer.context, hwc->renderer.surface)) { 316 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor-hybris initialized\n"); 317 | hwc->glamor = TRUE; 318 | } else { 319 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 320 | "glamor-hybris initialization failed\n"); 321 | } 322 | #ifndef __ANDROID__ 323 | } else { 324 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 325 | "Failed to load glamor-hybris module.\n"); 326 | } 327 | #endif // __ANDROID__ 328 | } 329 | #endif 330 | 331 | # define RETURN \ 332 | { FreeRec(pScrn);\ 333 | return FALSE;\ 334 | } 335 | 336 | void hwc_set_egl_platform(ScrnInfoPtr pScrn) 337 | { 338 | HWCPtr hwc = HWCPTR(pScrn); 339 | const char *egl_platform_str = xf86GetOptValString(hwc->Options, 340 | OPTION_EGL_PLATFORM); 341 | if (egl_platform_str) { 342 | setenv("EGL_PLATFORM", egl_platform_str, 1); 343 | } 344 | else { 345 | // Default to EGL_PLATFORM=hwcomposer 346 | setenv("EGL_PLATFORM", "hwcomposer", 0); 347 | } 348 | } 349 | 350 | /* Mandatory */ 351 | Bool 352 | PreInit(ScrnInfoPtr pScrn, int flags) 353 | { 354 | HWCPtr hwc; 355 | GDevPtr device = xf86GetEntityInfo(pScrn->entityList[0])->device; 356 | xf86CrtcPtr crtc; 357 | xf86OutputPtr output; 358 | const char *s; 359 | 360 | if (flags & PROBE_DETECT) 361 | return TRUE; 362 | 363 | /* Allocate the HWCRec driverPrivate */ 364 | if (!GetRec(pScrn)) { 365 | return FALSE; 366 | } 367 | 368 | hwc = HWCPTR(pScrn); 369 | pScrn->monitor = pScrn->confScreen->monitor; 370 | 371 | if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) 372 | return FALSE; 373 | else { 374 | /* Check that the returned depth is one we support */ 375 | switch (pScrn->depth) { 376 | case 8: 377 | case 15: 378 | case 16: 379 | case 24: 380 | case 30: 381 | break; 382 | default: 383 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 384 | "Given depth (%d) is not supported by this driver\n", 385 | pScrn->depth); 386 | return FALSE; 387 | } 388 | } 389 | 390 | xf86PrintDepthBpp(pScrn); 391 | if (pScrn->depth == 8) 392 | pScrn->rgbBits = 8; 393 | 394 | /* Get the depth24 pixmap format */ 395 | if (pScrn->depth == 24 && pix24bpp == 0) 396 | pix24bpp = xf86GetBppFromDepth(pScrn, 24); 397 | 398 | /* 399 | * This must happen after pScrn->display has been set because 400 | * xf86SetWeight references it. 401 | */ 402 | if (pScrn->depth > 8) { 403 | /* The defaults are OK for us */ 404 | rgb zeros = {0, 0, 0}; 405 | 406 | if (!xf86SetWeight(pScrn, zeros, zeros)) { 407 | return FALSE; 408 | } else { 409 | /* XXX check that weight returned is supported */ 410 | ; 411 | } 412 | } 413 | 414 | if (!xf86SetDefaultVisual(pScrn, -1)) 415 | return FALSE; 416 | 417 | if (pScrn->depth > 1) { 418 | Gamma zeros = {0.0, 0.0, 0.0}; 419 | 420 | if (!xf86SetGamma(pScrn, zeros)) 421 | return FALSE; 422 | } 423 | 424 | xf86CollectOptions(pScrn, device->options); 425 | /* Process the options */ 426 | if (!(hwc->Options = malloc(sizeof(Options)))) 427 | return FALSE; 428 | memcpy(hwc->Options, Options, sizeof(Options)); 429 | 430 | xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, hwc->Options); 431 | 432 | /* rotation */ 433 | hwc->rotation = HWC_ROTATE_NORMAL; 434 | if ((s = xf86GetOptValString(hwc->Options, OPTION_ROTATE))) 435 | { 436 | if(!xf86NameCmp(s, "CW")) { 437 | hwc->rotation = HWC_ROTATE_CW; 438 | xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "rotating screen clockwise\n"); 439 | } 440 | else if(!xf86NameCmp(s, "UD")) { 441 | hwc->rotation = HWC_ROTATE_UD; 442 | xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "rotating screen upside-down\n"); 443 | } 444 | else if(!xf86NameCmp(s, "CCW")) { 445 | hwc->rotation = HWC_ROTATE_CCW; 446 | xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "rotating screen counter-clockwise\n"); 447 | } 448 | else { 449 | xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 450 | "\"%s\" is not a valid value for Option \"Rotate\"\n", s); 451 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, 452 | "valid options are \"CW\", \"UD\", \"CCW\"\n"); 453 | } 454 | } 455 | 456 | hwc->swCursor = xf86ReturnOptValBool(hwc->Options, OPTION_SW_CURSOR, FALSE); 457 | if (hwc->swCursor) { 458 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, 459 | "hardware cursor disabled\n"); 460 | } 461 | 462 | hwc_set_egl_platform(pScrn); 463 | 464 | if (!hwc_hwcomposer_init(pScrn)) { 465 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 466 | "failed to initialize HWComposer API and layers\n"); 467 | return FALSE; 468 | } 469 | 470 | if (!hwc_lights_init(pScrn)) { 471 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, 472 | "failed to initialize lights module for backlight control\n"); 473 | } 474 | 475 | hwc_display_pre_init(pScrn); 476 | 477 | /* If monitor resolution is set on the command line, use it */ 478 | xf86SetDpi(pScrn, 0, 0); 479 | 480 | #ifndef __ANDROID__ 481 | if (xf86LoadSubModule(pScrn, "fb") == NULL) { 482 | RETURN; 483 | } 484 | #endif // __ANDROID__ 485 | 486 | if (!hwc->swCursor) { 487 | #ifndef __ANDROID__ 488 | if (!xf86LoadSubModule(pScrn, "ramdac")) 489 | RETURN; 490 | #endif // __ANDROID__ 491 | } 492 | 493 | /* We have no contiguous physical fb in physical memory */ 494 | pScrn->memPhysBase = 0; 495 | pScrn->fbOffset = 0; 496 | 497 | if (!hwc_egl_renderer_init(pScrn)) { 498 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 499 | "failed to initialize EGL renderer\n"); 500 | return FALSE; 501 | } 502 | 503 | if (!hwc_init_hybris_native_buffer(pScrn)) { 504 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 505 | "failed to initialize libhybris native buffer EGL extension\n"); 506 | return FALSE; 507 | } 508 | 509 | hwc->buffer = NULL; 510 | 511 | hwc->glamor = FALSE; 512 | hwc->drihybris = FALSE; 513 | #ifdef ENABLE_GLAMOR 514 | try_enable_glamor(pScrn); 515 | #endif 516 | 517 | return TRUE; 518 | } 519 | #undef RETURN 520 | 521 | /* Mandatory */ 522 | static Bool 523 | EnterVT(VT_FUNC_ARGS_DECL) 524 | { 525 | return TRUE; 526 | } 527 | 528 | /* Mandatory */ 529 | static void 530 | LeaveVT(VT_FUNC_ARGS_DECL) 531 | { 532 | } 533 | 534 | static void 535 | LoadPalette( 536 | ScrnInfoPtr pScrn, 537 | int numColors, 538 | int *indices, 539 | LOCO *colors, 540 | VisualPtr pVisual 541 | ){ 542 | int i, index, shift, Gshift; 543 | HWCPtr hwc = HWCPTR(pScrn); 544 | 545 | switch(pScrn->depth) { 546 | case 15: 547 | shift = Gshift = 1; 548 | break; 549 | case 16: 550 | shift = 0; 551 | Gshift = 0; 552 | break; 553 | default: 554 | shift = Gshift = 0; 555 | break; 556 | } 557 | 558 | for(i = 0; i < numColors; i++) { 559 | index = indices[i]; 560 | hwc->colors[index].red = colors[index].red << shift; 561 | hwc->colors[index].green = colors[index].green << Gshift; 562 | hwc->colors[index].blue = colors[index].blue << shift; 563 | } 564 | } 565 | 566 | static void hwcBlockHandler(ScreenPtr pScreen, void *timeout) 567 | { 568 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 569 | HWCPtr hwc = HWCPTR(pScrn); 570 | PixmapPtr rootPixmap; 571 | int err; 572 | 573 | pScreen->BlockHandler = hwc->BlockHandler; 574 | pScreen->BlockHandler(pScreen, timeout); 575 | pScreen->BlockHandler = hwcBlockHandler; 576 | 577 | if (hwc->damage && hwc->dpmsMode == DPMSModeOn) { 578 | RegionPtr dirty = DamageRegion(hwc->damage); 579 | unsigned num_cliprects = REGION_NUM_RECTS(dirty); 580 | 581 | if (num_cliprects) { 582 | DamageEmpty(hwc->damage); 583 | hwc->dirty = TRUE; 584 | } 585 | } 586 | } 587 | 588 | static Bool 589 | CreateScreenResources(ScreenPtr pScreen) 590 | { 591 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 592 | HWCPtr hwc = HWCPTR(pScrn); 593 | PixmapPtr rootPixmap; 594 | Bool ret; 595 | void *pixels = NULL; 596 | int err; 597 | 598 | pScreen->CreateScreenResources = hwc->CreateScreenResources; 599 | ret = pScreen->CreateScreenResources(pScreen); 600 | pScreen->CreateScreenResources = CreateScreenResources; 601 | 602 | rootPixmap = pScreen->GetScreenPixmap(pScreen); 603 | 604 | #ifdef ENABLE_GLAMOR 605 | if (hwc->glamor) { 606 | pScreen->DestroyPixmap(rootPixmap); 607 | 608 | rootPixmap = glamor_create_pixmap(pScreen, 609 | pScreen->width, 610 | pScreen->height, 611 | pScreen->rootDepth, 612 | GLAMOR_CREATE_NO_LARGE); 613 | pScreen->SetScreenPixmap(rootPixmap); 614 | } 615 | #endif 616 | 617 | err = hwc->renderer.eglHybrisCreateNativeBuffer(pScrn->virtualX, pScrn->virtualY, 618 | HYBRIS_USAGE_HW_TEXTURE | 619 | HYBRIS_USAGE_SW_READ_OFTEN|HYBRIS_USAGE_SW_WRITE_OFTEN, 620 | HYBRIS_PIXEL_FORMAT_RGBA_8888, 621 | &hwc->stride, &hwc->buffer); 622 | 623 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, "alloc: status=%d, stride=%d\n", err, hwc->stride); 624 | 625 | hwc_egl_renderer_screen_init(pScreen); 626 | 627 | #ifdef ENABLE_GLAMOR 628 | if (hwc->glamor) 629 | hwc->renderer.rootTexture = glamor_get_pixmap_texture(rootPixmap); 630 | #endif 631 | 632 | err = hwc->renderer.eglHybrisLockNativeBuffer(hwc->buffer, 633 | HYBRIS_USAGE_SW_READ_OFTEN|HYBRIS_USAGE_SW_WRITE_OFTEN, 634 | 0, 0, hwc->stride, pScrn->virtualY, &pixels); 635 | 636 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, "gralloc lock returns %i\n", err); 637 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, "lock to vaddr %p\n", pixels); 638 | 639 | if (!hwc->glamor) { 640 | if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels)) 641 | FatalError("Couldn't adjust screen pixmap\n"); 642 | } 643 | 644 | hwc->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, 645 | pScreen, rootPixmap); 646 | 647 | if (hwc->damage) { 648 | DamageRegister(&rootPixmap->drawable, hwc->damage); 649 | hwc->dirty = FALSE; 650 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); 651 | } 652 | else { 653 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 654 | "Failed to create screen damage record\n"); 655 | return FALSE; 656 | } 657 | 658 | return ret; 659 | } 660 | 661 | static CARD32 hwc_update_by_timer(OsTimerPtr timer, CARD32 time, void *ptr) { 662 | ScreenPtr pScreen = (ScreenPtr) ptr; 663 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 664 | HWCPtr hwc = HWCPTR(pScrn); 665 | PixmapPtr rootPixmap; 666 | int err; 667 | 668 | if (hwc->dirty && hwc->dpmsMode == DPMSModeOn) { 669 | void *pixels = NULL; 670 | rootPixmap = pScreen->GetScreenPixmap(pScreen); 671 | hwc->renderer.eglHybrisUnlockNativeBuffer(hwc->buffer); 672 | 673 | hwc_egl_renderer_update(pScreen); 674 | 675 | err = hwc->renderer.eglHybrisLockNativeBuffer(hwc->buffer, 676 | HYBRIS_USAGE_SW_READ_OFTEN|HYBRIS_USAGE_SW_WRITE_OFTEN, 677 | 0, 0, hwc->stride, pScrn->virtualY, &pixels); 678 | 679 | if (!hwc->glamor) { 680 | if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels)) 681 | FatalError("Couldn't adjust screen pixmap\n"); 682 | } 683 | 684 | hwc->dirty = FALSE; 685 | } 686 | 687 | return TIMER_DELAY; 688 | } 689 | 690 | /* Mandatory */ 691 | static Bool 692 | ScreenInit(SCREEN_INIT_ARGS_DECL) 693 | { 694 | ScrnInfoPtr pScrn; 695 | HWCPtr hwc; 696 | int ret; 697 | VisualPtr visual; 698 | void *pixels; 699 | 700 | /* 701 | * we need to get the ScrnInfoRec for this screen, so let's allocate 702 | * one first thing 703 | */ 704 | pScrn = xf86ScreenToScrn(pScreen); 705 | hwc = HWCPTR(pScrn); 706 | 707 | /* 708 | * Reset visual list. 709 | */ 710 | miClearVisualTypes(); 711 | 712 | /* Setup the visuals we support. */ 713 | 714 | if (!miSetVisualTypes(pScrn->depth, 715 | miGetDefaultVisualMask(pScrn->depth), 716 | pScrn->rgbBits, pScrn->defaultVisual)) 717 | return FALSE; 718 | 719 | if (!miSetPixmapDepths ()) return FALSE; 720 | 721 | /* 722 | * Call the framebuffer layer's ScreenInit function, and fill in other 723 | * pScreen fields. 724 | */ 725 | ret = fbScreenInit(pScreen, NULL, 726 | pScrn->virtualX, pScrn->virtualY, 727 | pScrn->xDpi, pScrn->yDpi, 728 | pScrn->displayWidth, pScrn->bitsPerPixel); 729 | if (!ret) 730 | return FALSE; 731 | 732 | if (pScrn->depth > 8) { 733 | /* Fixup RGB ordering */ 734 | visual = pScreen->visuals + pScreen->numVisuals; 735 | while (--visual >= pScreen->visuals) { 736 | if ((visual->class | DynamicClass) == DirectColor) { 737 | visual->offsetRed = pScrn->offset.red; 738 | visual->offsetGreen = pScrn->offset.green; 739 | visual->offsetBlue = pScrn->offset.blue; 740 | visual->redMask = pScrn->mask.red; 741 | visual->greenMask = pScrn->mask.green; 742 | visual->blueMask = pScrn->mask.blue; 743 | } 744 | } 745 | } 746 | 747 | /* must be after RGB ordering fixed */ 748 | fbPictureInit(pScreen, 0, 0); 749 | 750 | #ifdef ENABLE_GLAMOR 751 | if (hwc->glamor && !glamor_init(pScreen, GLAMOR_USE_EGL_SCREEN)) { 752 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 753 | "Failed to initialize glamor at ScreenInit() time.\n"); 754 | return FALSE; 755 | } 756 | #endif 757 | 758 | xf86SetBlackWhitePixels(pScreen); 759 | 760 | hwc->CreateScreenResources = pScreen->CreateScreenResources; 761 | pScreen->CreateScreenResources = CreateScreenResources; 762 | 763 | xf86SetBackingStore(pScreen); 764 | xf86SetSilkenMouse(pScreen); 765 | 766 | /* Initialise cursor functions */ 767 | miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 768 | 769 | /* Need to extend HWcursor support to handle mask interleave */ 770 | if (!hwc->swCursor) { 771 | hwc->cursorWidth = 64; 772 | hwc->cursorHeight = 64; 773 | 774 | xf86_cursors_init(pScreen, hwc->cursorWidth, hwc->cursorHeight, 775 | HARDWARE_CURSOR_UPDATE_UNHIDDEN | 776 | HARDWARE_CURSOR_ARGB); 777 | } 778 | 779 | /* Initialise default colourmap */ 780 | if(!miCreateDefColormap(pScreen)) 781 | return FALSE; 782 | 783 | if (!xf86HandleColormaps(pScreen, 1024, pScrn->rgbBits, 784 | LoadPalette, NULL, 785 | CMAP_PALETTED_TRUECOLOR 786 | | CMAP_RELOAD_ON_MODE_SWITCH)) 787 | return FALSE; 788 | 789 | if (!xf86CrtcScreenInit(pScreen)) 790 | return FALSE; 791 | 792 | pScreen->SaveScreen = SaveScreen; 793 | 794 | /* Wrap the current CloseScreen function */ 795 | hwc->CloseScreen = pScreen->CloseScreen; 796 | pScreen->CloseScreen = CloseScreen; 797 | 798 | xf86DPMSInit(pScreen, xf86DPMSSet, 0); 799 | hwc->dpmsMode = DPMSModeOn; 800 | 801 | if (hwc->glamor) { 802 | XF86VideoAdaptorPtr glamor_adaptor; 803 | 804 | glamor_adaptor = glamor_xv_init(pScreen, 16); 805 | if (glamor_adaptor != NULL) 806 | xf86XVScreenInit(pScreen, &glamor_adaptor, 1); 807 | else 808 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 809 | "Failed to initialize XV support.\n"); 810 | } 811 | 812 | /* Report any unused options (only for the first generation) */ 813 | if (serverGeneration == 1) { 814 | xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 815 | } 816 | 817 | /* Wrap the current BlockHandler function */ 818 | hwc->BlockHandler = pScreen->BlockHandler; 819 | pScreen->BlockHandler = hwcBlockHandler; 820 | 821 | #ifdef ENABLE_DRIHYBRIS 822 | if (hwc->drihybris) { 823 | drihybris_extension_init(); 824 | } 825 | #endif 826 | if (!hwc_present_screen_init(pScreen)) { 827 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 828 | "Failed to initialize the Present extension.\n"); 829 | } 830 | 831 | TimerSet(hwc->timer, 0, TIMER_DELAY, hwc_update_by_timer, (void*) pScreen); 832 | 833 | return TRUE; 834 | } 835 | 836 | /* Mandatory */ 837 | Bool 838 | SwitchMode(SWITCH_MODE_ARGS_DECL) 839 | { 840 | return TRUE; 841 | } 842 | 843 | /* Mandatory */ 844 | void 845 | AdjustFrame(ADJUST_FRAME_ARGS_DECL) 846 | { 847 | } 848 | 849 | /* Mandatory */ 850 | static Bool 851 | CloseScreen(CLOSE_SCREEN_ARGS_DECL) 852 | { 853 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 854 | HWCPtr hwc = HWCPTR(pScrn); 855 | 856 | TimerCancel(hwc->timer); 857 | 858 | if (hwc->damage) { 859 | DamageUnregister(hwc->damage); 860 | DamageDestroy(hwc->damage); 861 | hwc->damage = NULL; 862 | } 863 | 864 | hwc_egl_renderer_screen_close(pScreen); 865 | 866 | if (hwc->buffer != NULL) 867 | { 868 | hwc->renderer.eglHybrisUnlockNativeBuffer(hwc->buffer); 869 | hwc->renderer.eglHybrisReleaseNativeBuffer(hwc->buffer); 870 | hwc->buffer = NULL; 871 | } 872 | 873 | if (hwc->CursorInfo) 874 | xf86DestroyCursorInfoRec(hwc->CursorInfo); 875 | 876 | pScrn->vtSema = FALSE; 877 | pScreen->CloseScreen = hwc->CloseScreen; 878 | return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 879 | } 880 | 881 | /* Optional */ 882 | static void 883 | FreeScreen(FREE_SCREEN_ARGS_DECL) 884 | { 885 | SCRN_INFO_PTR(arg); 886 | FreeRec(pScrn); 887 | } 888 | 889 | static Bool 890 | SaveScreen(ScreenPtr pScreen, int mode) 891 | { 892 | return TRUE; 893 | } 894 | 895 | /* Optional */ 896 | static ModeStatus 897 | ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 898 | { 899 | return(MODE_OK); 900 | } 901 | 902 | #ifndef HW_SKIP_CONSOLE 903 | #define HW_SKIP_CONSOLE 4 904 | #endif 905 | 906 | static Bool 907 | hwc_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 908 | { 909 | CARD32 *flag; 910 | 911 | switch (op) { 912 | case GET_REQUIRED_HW_INTERFACES: 913 | flag = (CARD32*)ptr; 914 | (*flag) = HW_SKIP_CONSOLE; 915 | return TRUE; 916 | default: 917 | return FALSE; 918 | } 919 | } 920 | -------------------------------------------------------------------------------- /src/driver.h: -------------------------------------------------------------------------------- 1 | /* All drivers should typically include these */ 2 | #include "xf86.h" 3 | #include "xf86_OSproc.h" 4 | 5 | #include "xf86Cursor.h" 6 | 7 | #ifdef XvExtension 8 | #include "xf86xv.h" 9 | #include 10 | #endif 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #define MESA_EGL_NO_X11_HEADERS 1 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "compat-api.h" 25 | 26 | /* function prototypes */ 27 | 28 | extern Bool SwitchMode(SWITCH_MODE_ARGS_DECL); 29 | extern void AdjustFrame(ADJUST_FRAME_ARGS_DECL); 30 | 31 | /* globals */ 32 | typedef struct _color 33 | { 34 | int red; 35 | int green; 36 | int blue; 37 | } dummy_colors; 38 | 39 | Bool hwc_display_pre_init(ScrnInfoPtr pScrn); 40 | Bool hwc_hwcomposer_init(ScrnInfoPtr pScrn); 41 | void hwc_hwcomposer_close(ScrnInfoPtr pScrn); 42 | Bool hwc_lights_init(ScrnInfoPtr pScrn); 43 | 44 | struct ANativeWindow *hwc_get_native_window(ScrnInfoPtr pScrn); 45 | void hwc_toggle_screen_brightness(ScrnInfoPtr pScrn); 46 | void hwc_set_power_mode(ScrnInfoPtr pScrn, int disp, int mode); 47 | 48 | Bool hwc_init_hybris_native_buffer(ScrnInfoPtr pScrn); 49 | Bool hwc_egl_renderer_init(ScrnInfoPtr pScrn); 50 | void hwc_egl_renderer_close(ScrnInfoPtr pScrn); 51 | void hwc_egl_renderer_screen_init(ScreenPtr pScreen); 52 | void hwc_egl_renderer_screen_close(ScreenPtr pScreen); 53 | void hwc_egl_renderer_update(ScreenPtr pScreen); 54 | 55 | void hwc_ortho_2d(float* mat, float left, float right, float bottom, float top); 56 | GLuint hwc_link_program(const GLchar *vert_src, const GLchar *frag_src); 57 | 58 | Bool hwc_present_screen_init(ScreenPtr pScreen); 59 | Bool hwc_cursor_init(ScreenPtr pScreen); 60 | 61 | typedef enum { 62 | HWC_ROTATE_NORMAL, 63 | HWC_ROTATE_CW, 64 | HWC_ROTATE_UD, 65 | HWC_ROTATE_CCW 66 | } hwc_rotation; 67 | 68 | typedef struct { 69 | GLuint program; 70 | GLint position; 71 | GLint texcoords; 72 | GLint transform; 73 | GLint texture; 74 | } hwc_renderer_shader; 75 | 76 | typedef struct { 77 | PFNEGLHYBRISCREATENATIVEBUFFERPROC eglHybrisCreateNativeBuffer; 78 | PFNEGLHYBRISLOCKNATIVEBUFFERPROC eglHybrisLockNativeBuffer; 79 | PFNEGLHYBRISUNLOCKNATIVEBUFFERPROC eglHybrisUnlockNativeBuffer; 80 | PFNEGLHYBRISRELEASENATIVEBUFFERPROC eglHybrisReleaseNativeBuffer; 81 | PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; 82 | PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; 83 | PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; 84 | 85 | EGLDisplay display; 86 | EGLSurface surface; 87 | EGLContext context; 88 | GLuint rootTexture; 89 | GLuint cursorTexture; 90 | 91 | float projection[16]; 92 | EGLImageKHR image; 93 | 94 | hwc_renderer_shader rootShader; 95 | hwc_renderer_shader projShader; 96 | } hwc_renderer_rec, *hwc_renderer_ptr; 97 | 98 | typedef struct HWCRec 99 | { 100 | /* options */ 101 | OptionInfoPtr Options; 102 | Bool swCursor; 103 | /* proc pointer */ 104 | CloseScreenProcPtr CloseScreen; 105 | CreateScreenResourcesProcPtr CreateScreenResources; 106 | xf86CursorInfoPtr CursorInfo; 107 | ScreenBlockHandlerProcPtr BlockHandler; 108 | OsTimerPtr timer; 109 | 110 | dummy_colors colors[1024]; 111 | Bool (*CreateWindow)() ; /* wrapped CreateWindow */ 112 | Bool prop; 113 | 114 | DamagePtr damage; 115 | Bool dirty; 116 | Bool glamor; 117 | Bool drihybris; 118 | hwc_rotation rotation; 119 | 120 | gralloc_module_t *gralloc; 121 | alloc_device_t *alloc; 122 | void *libminisf; 123 | 124 | hwc_composer_device_1_t *hwcDevicePtr; 125 | hwc_display_contents_1_t **hwcContents; 126 | hwc_layer_1_t *fblayer; 127 | uint32_t hwcVersion; 128 | int hwcWidth; 129 | int hwcHeight; 130 | 131 | hwc_renderer_rec renderer; 132 | EGLClientBuffer buffer; 133 | int stride; 134 | 135 | Bool cursorShown; 136 | xf86CursorInfoPtr cursorInfo; 137 | int cursorX; 138 | int cursorY; 139 | int cursorWidth; 140 | int cursorHeight; 141 | 142 | struct light_device_t *lightsDevice; 143 | int screenBrightness; 144 | 145 | DisplayModePtr modes; 146 | int dpmsMode; 147 | } HWCRec, *HWCPtr; 148 | 149 | /* The privates of the hwcomposer driver */ 150 | #define HWCPTR(p) ((HWCPtr)((p)->driverPrivate)) 151 | 152 | -------------------------------------------------------------------------------- /src/glutils.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include "config.h" 3 | #endif 4 | 5 | #include "driver.h" 6 | 7 | void hwc_ortho_2d(float* mat, float left, float right, float bottom, float top) 8 | { 9 | const float zNear = -1.0f; 10 | const float zFar = 1.0f; 11 | const float inv_z = 1.0f / (zFar - zNear); 12 | const float inv_y = 1.0f / (top - bottom); 13 | const float inv_x = 1.0f / (right - left); 14 | 15 | // first column 16 | *mat++ = (2.0f*inv_x); 17 | *mat++ = (0.0f); 18 | *mat++ = (0.0f); 19 | *mat++ = (0.0f); 20 | 21 | // second 22 | *mat++ = (0.0f); 23 | *mat++ = (2.0*inv_y); 24 | *mat++ = (0.0f); 25 | *mat++ = (0.0f); 26 | 27 | // third 28 | *mat++ = (0.0f); 29 | *mat++ = (0.0f); 30 | *mat++ = (-2.0f*inv_z); 31 | *mat++ = (0.0f); 32 | 33 | // fourth 34 | *mat++ = (-(right + left)*inv_x); 35 | *mat++ = (-(top + bottom)*inv_y); 36 | *mat++ = (-(zFar + zNear)*inv_z); 37 | *mat++ = (1.0f); 38 | } 39 | 40 | /* The following code is based on 41 | * https://github.com/swaywm/wlroots/blob/master/render/gles2/renderer.c */ 42 | static GLuint compile_shader(GLuint type, const GLchar *src) { 43 | GLuint shader = glCreateShader(type); 44 | glShaderSource(shader, 1, &src, NULL); 45 | glCompileShader(shader); 46 | 47 | GLint ok; 48 | glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); 49 | if (ok == GL_FALSE) { 50 | glDeleteShader(shader); 51 | shader = 0; 52 | } 53 | return shader; 54 | } 55 | 56 | GLuint hwc_link_program(const GLchar *vert_src, const GLchar *frag_src) { 57 | GLuint vert = compile_shader(GL_VERTEX_SHADER, vert_src); 58 | if (!vert) { 59 | return 0; 60 | } 61 | 62 | GLuint frag = compile_shader(GL_FRAGMENT_SHADER, frag_src); 63 | if (!frag) { 64 | glDeleteShader(vert); 65 | return 0; 66 | } 67 | 68 | GLuint prog = glCreateProgram(); 69 | glAttachShader(prog, vert); 70 | glAttachShader(prog, frag); 71 | glLinkProgram(prog); 72 | 73 | glDetachShader(prog, vert); 74 | glDetachShader(prog, frag); 75 | glDeleteShader(vert); 76 | glDeleteShader(frag); 77 | 78 | GLint ok; 79 | glGetProgramiv(prog, GL_LINK_STATUS, &ok); 80 | if (ok == GL_FALSE) { 81 | glDeleteProgram(prog); 82 | return 0; 83 | } 84 | 85 | return prog; 86 | } 87 | -------------------------------------------------------------------------------- /src/hwcomposer.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include "config.h" 3 | #endif 4 | 5 | #include 6 | #include "xf86.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "driver.h" 21 | 22 | void *android_dlopen(const char *filename, int flags); 23 | void *android_dlsym(void *handle, const char *symbol); 24 | int android_dlclose(void *handle); 25 | 26 | inline static uint32_t interpreted_version(hw_device_t *hwc_device) 27 | { 28 | uint32_t version = hwc_device->version; 29 | 30 | if ((version & 0xffff0000) == 0) { 31 | // Assume header version is always 1 32 | uint32_t header_version = 1; 33 | 34 | // Legacy version encoding 35 | version = (version << 16) | header_version; 36 | } 37 | return version; 38 | } 39 | 40 | void hwc_set_power_mode(ScrnInfoPtr pScrn, int disp, int mode) 41 | { 42 | HWCPtr hwc = HWCPTR(pScrn); 43 | 44 | hwc_composer_device_1_t *hwcDevicePtr = hwc->hwcDevicePtr; 45 | hw_device_t *hwcDevice = &hwcDevicePtr->common; 46 | 47 | uint32_t hwc_version = hwc->hwcVersion = interpreted_version(hwcDevice); 48 | 49 | #ifdef HWC_DEVICE_API_VERSION_1_4 50 | if (hwc_version == HWC_DEVICE_API_VERSION_1_4) { 51 | hwcDevicePtr->setPowerMode(hwcDevicePtr, disp, (mode) ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF); 52 | } else 53 | #endif 54 | #ifdef HWC_DEVICE_API_VERSION_1_5 55 | if (hwc_version == HWC_DEVICE_API_VERSION_1_5) { 56 | hwcDevicePtr->setPowerMode(hwcDevicePtr, disp, (mode) ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF); 57 | } else 58 | #endif 59 | hwcDevicePtr->blank(hwcDevicePtr, disp, (mode) ? 0 : 1); 60 | } 61 | 62 | void hwc_start_fake_surfaceflinger(ScrnInfoPtr pScrn) { 63 | HWCPtr hwc = HWCPTR(pScrn); 64 | void (*startMiniSurfaceFlinger)(void) = NULL; 65 | 66 | // Adapted from https://github.com/mer-hybris/qt5-qpa-hwcomposer-plugin/blob/master/hwcomposer/hwcomposer_backend.cpp#L88 67 | 68 | // A reason for calling this method here is to initialize the binder 69 | // thread pool such that services started from for example the 70 | // hwcomposer plugin don't get stuck. 71 | 72 | hwc->libminisf = android_dlopen("libminisf.so", RTLD_LAZY); 73 | 74 | if (hwc->libminisf) { 75 | startMiniSurfaceFlinger = (void(*)(void))android_dlsym(hwc->libminisf, "startMiniSurfaceFlinger"); 76 | } 77 | 78 | if (startMiniSurfaceFlinger) { 79 | startMiniSurfaceFlinger(); 80 | } else { 81 | xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "libminisf is incompatible or missing. Can not possibly start the fake SurfaceFlinger service.\n"); 82 | } 83 | } 84 | 85 | Bool hwc_hwcomposer_init(ScrnInfoPtr pScrn) 86 | { 87 | HWCPtr hwc = HWCPTR(pScrn); 88 | int err; 89 | 90 | hw_module_t const* module = NULL; 91 | err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); 92 | assert(err == 0); 93 | 94 | hwc->gralloc = (gralloc_module_t*) module; 95 | err = gralloc_open((const hw_module_t *) hwc->gralloc, &hwc->alloc); 96 | 97 | framebuffer_device_t* fbDev = NULL; 98 | framebuffer_open(module, &fbDev); 99 | 100 | hwc_start_fake_surfaceflinger(pScrn); 101 | 102 | hw_module_t *hwcModule = 0; 103 | 104 | err = hw_get_module(HWC_HARDWARE_MODULE_ID, (const hw_module_t **) &hwcModule); 105 | assert(err == 0); 106 | 107 | hwc_composer_device_1_t *hwcDevicePtr = 0; 108 | err = hwc_open_1(hwcModule, &hwcDevicePtr); 109 | assert(err == 0); 110 | 111 | hwc->hwcDevicePtr = hwcDevicePtr; 112 | hw_device_t *hwcDevice = &hwcDevicePtr->common; 113 | 114 | hwc_set_power_mode(pScrn, HWC_DISPLAY_PRIMARY, 1); uint32_t hwc_version = hwc->hwcVersion = interpreted_version(hwcDevice); 115 | 116 | uint32_t configs[5]; 117 | size_t numConfigs = 5; 118 | 119 | err = hwcDevicePtr->getDisplayConfigs(hwcDevicePtr, HWC_DISPLAY_PRIMARY, configs, &numConfigs); 120 | assert (err == 0); 121 | 122 | int32_t attr_values[2]; 123 | uint32_t attributes[] = { HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_NO_ATTRIBUTE }; 124 | 125 | hwcDevicePtr->getDisplayAttributes(hwcDevicePtr, HWC_DISPLAY_PRIMARY, 126 | configs[0], attributes, attr_values); 127 | 128 | xf86DrvMsg(pScrn->scrnIndex, X_INFO, "width: %i height: %i\n", attr_values[0], attr_values[1]); 129 | hwc->hwcWidth = attr_values[0]; 130 | hwc->hwcHeight = attr_values[1]; 131 | 132 | size_t size = sizeof(hwc_display_contents_1_t) + 2 * sizeof(hwc_layer_1_t); 133 | hwc_display_contents_1_t *list = (hwc_display_contents_1_t *) malloc(size); 134 | hwc->hwcContents = (hwc_display_contents_1_t **) malloc(HWC_NUM_DISPLAY_TYPES * sizeof(hwc_display_contents_1_t *)); 135 | const hwc_rect_t r = { 0, 0, attr_values[0], attr_values[1] }; 136 | 137 | int counter = 0; 138 | for (; counter < HWC_NUM_DISPLAY_TYPES; counter++) 139 | hwc->hwcContents[counter] = NULL; 140 | // Assign the layer list only to the first display, 141 | // otherwise HWC might freeze if others are disconnected 142 | hwc->hwcContents[0] = list; 143 | 144 | hwc_layer_1_t *layer = &list->hwLayers[0]; 145 | memset(layer, 0, sizeof(hwc_layer_1_t)); 146 | layer->compositionType = HWC_FRAMEBUFFER; 147 | layer->hints = 0; 148 | layer->flags = 0; 149 | layer->handle = 0; 150 | layer->transform = 0; 151 | layer->blending = HWC_BLENDING_NONE; 152 | #ifdef HWC_DEVICE_API_VERSION_1_3 153 | layer->sourceCropf.top = 0.0f; 154 | layer->sourceCropf.left = 0.0f; 155 | layer->sourceCropf.bottom = (float) attr_values[1]; 156 | layer->sourceCropf.right = (float) attr_values[0]; 157 | #else 158 | layer->sourceCrop = r; 159 | #endif 160 | layer->displayFrame = r; 161 | layer->visibleRegionScreen.numRects = 1; 162 | layer->visibleRegionScreen.rects = &layer->displayFrame; 163 | layer->acquireFenceFd = -1; 164 | layer->releaseFenceFd = -1; 165 | #if (ANDROID_VERSION_MAJOR >= 4) && (ANDROID_VERSION_MINOR >= 3) || (ANDROID_VERSION_MAJOR >= 5) 166 | // We've observed that qualcomm chipsets enters into compositionType == 6 167 | // (HWC_BLIT), an undocumented composition type which gives us rendering 168 | // glitches and warnings in logcat. By setting the planarAlpha to non- 169 | // opaque, we attempt to force the HWC into using HWC_FRAMEBUFFER for this 170 | // layer so the HWC_FRAMEBUFFER_TARGET layer actually gets used. 171 | int tryToForceGLES = getenv("QPA_HWC_FORCE_GLES") != NULL; 172 | layer->planeAlpha = tryToForceGLES ? 1 : 255; 173 | #endif 174 | #ifdef HWC_DEVICE_API_VERSION_1_5 175 | layer->surfaceDamage.numRects = 0; 176 | #endif 177 | 178 | hwc->fblayer = layer = &list->hwLayers[1]; 179 | memset(layer, 0, sizeof(hwc_layer_1_t)); 180 | layer->compositionType = HWC_FRAMEBUFFER_TARGET; 181 | layer->hints = 0; 182 | layer->flags = 0; 183 | layer->handle = 0; 184 | layer->transform = 0; 185 | layer->blending = HWC_BLENDING_NONE; 186 | #ifdef HWC_DEVICE_API_VERSION_1_3 187 | layer->sourceCropf.top = 0.0f; 188 | layer->sourceCropf.left = 0.0f; 189 | layer->sourceCropf.bottom = (float) attr_values[1]; 190 | layer->sourceCropf.right = (float) attr_values[0]; 191 | #else 192 | layer->sourceCrop = r; 193 | #endif 194 | layer->displayFrame = r; 195 | layer->visibleRegionScreen.numRects = 1; 196 | layer->visibleRegionScreen.rects = &layer->displayFrame; 197 | layer->acquireFenceFd = -1; 198 | layer->releaseFenceFd = -1; 199 | #if (ANDROID_VERSION_MAJOR >= 4) && (ANDROID_VERSION_MINOR >= 3) || (ANDROID_VERSION_MAJOR >= 5) 200 | layer->planeAlpha = 0xff; 201 | #endif 202 | #ifdef HWC_DEVICE_API_VERSION_1_5 203 | layer->surfaceDamage.numRects = 0; 204 | #endif 205 | 206 | list->retireFenceFd = -1; 207 | list->flags = HWC_GEOMETRY_CHANGED; 208 | list->numHwLayers = 2; 209 | 210 | return TRUE; 211 | } 212 | 213 | void hwc_hwcomposer_close(ScrnInfoPtr pScrn) 214 | { 215 | } 216 | 217 | static void present(void *user_data, struct ANativeWindow *window, 218 | struct ANativeWindowBuffer *buffer) 219 | { 220 | ScrnInfoPtr pScrn = (ScrnInfoPtr)user_data; 221 | HWCPtr hwc = HWCPTR(pScrn); 222 | 223 | hwc_display_contents_1_t **contents = hwc->hwcContents; 224 | hwc_layer_1_t *fblayer = hwc->fblayer; 225 | hwc_composer_device_1_t *hwcdevice = hwc->hwcDevicePtr; 226 | 227 | int oldretire = contents[0]->retireFenceFd; 228 | contents[0]->retireFenceFd = -1; 229 | 230 | fblayer->handle = buffer->handle; 231 | fblayer->acquireFenceFd = HWCNativeBufferGetFence(buffer); 232 | fblayer->releaseFenceFd = -1; 233 | int err = hwcdevice->prepare(hwcdevice, HWC_NUM_DISPLAY_TYPES, contents); 234 | assert(err == 0); 235 | 236 | err = hwcdevice->set(hwcdevice, HWC_NUM_DISPLAY_TYPES, contents); 237 | /* in Android, SurfaceFlinger ignores the return value as not all 238 | display types may be supported */ 239 | HWCNativeBufferSetFence(buffer, fblayer->releaseFenceFd); 240 | 241 | if (oldretire != -1) 242 | { 243 | sync_wait(oldretire, -1); 244 | close(oldretire); 245 | } 246 | } 247 | 248 | struct ANativeWindow *hwc_get_native_window(ScrnInfoPtr pScrn) { 249 | HWCPtr hwc = HWCPTR(pScrn); 250 | struct ANativeWindow *win = HWCNativeWindowCreate(hwc->hwcWidth, hwc->hwcHeight, HAL_PIXEL_FORMAT_RGBA_8888, present, pScrn); 251 | return win; 252 | } 253 | 254 | void hwc_toggle_screen_brightness(ScrnInfoPtr pScrn) 255 | { 256 | HWCPtr hwc = HWCPTR(pScrn); 257 | struct light_state_t state; 258 | int brightness; 259 | 260 | if (!hwc->lightsDevice) { 261 | return; 262 | } 263 | brightness = (hwc->dpmsMode == DPMSModeOn) ? 264 | hwc->screenBrightness : 0; 265 | 266 | state.flashMode = LIGHT_FLASH_NONE; 267 | state.brightnessMode = BRIGHTNESS_MODE_USER; 268 | 269 | state.color = (int)((0xffU << 24) | (brightness << 16) | 270 | (brightness << 8) | brightness); 271 | hwc->lightsDevice->set_light(hwc->lightsDevice, &state); 272 | } 273 | -------------------------------------------------------------------------------- /src/present.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Intel Corporation 3 | * 4 | * Permission to use, copy, modify, distribute, and sell this software and its 5 | * documentation for any purpose is hereby granted without fee, provided that 6 | * the above copyright notice appear in all copies and that both that copyright 7 | * notice and this permission notice appear in supporting documentation, and 8 | * that the name of the copyright holders not be used in advertising or 9 | * publicity pertaining to distribution of the software without specific, 10 | * written prior permission. The copyright holders make no representations 11 | * about the suitability of this software for any purpose. It is provided "as 12 | * is" without express or implied warranty. 13 | * 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 | * OF THIS SOFTWARE. 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | #include "config.h" 25 | #endif 26 | 27 | #include 28 | #include 29 | 30 | #include "driver.h" 31 | 32 | static present_screen_info_rec hwcomposer_present_screen_info = { 33 | .version = PRESENT_SCREEN_INFO_VERSION 34 | }; 35 | 36 | Bool 37 | hwc_present_screen_init(ScreenPtr pScreen) 38 | { 39 | return present_screen_init(pScreen, NULL); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/renderer.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include "config.h" 3 | #endif 4 | 5 | #include 6 | #include "xf86.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "driver.h" 15 | 16 | extern const char vertex_src[]; 17 | extern const char vertex_mvp_src[]; 18 | extern const char fragment_src[]; 19 | extern const char fragment_src_bgra[]; 20 | 21 | static const GLfloat squareVertices[] = { 22 | -1.0f, -1.0f, 23 | 1.0f, -1.0f, 24 | -1.0f, 1.0f, 25 | 1.0f, 1.0f, 26 | }; 27 | 28 | static const GLfloat textureVertices[][8] = { 29 | { // NORMAL - 0 degrees 30 | 0.0f, 1.0f, 31 | 1.0f, 1.0f, 32 | 0.0f, 0.0f, 33 | 1.0f, 0.0f, 34 | }, 35 | { // CW - 90 degrees 36 | 1.0f, 1.0f, 37 | 1.0f, 0.0f, 38 | 0.0f, 1.0f, 39 | 0.0f, 0.0f, 40 | }, 41 | { // UD - 180 degrees 42 | 1.0f, 0.0f, 43 | 0.0f, 0.0f, 44 | 1.0f, 1.0f, 45 | 0.0f, 1.0f, 46 | }, 47 | { // CCW - 270 degrees 48 | 0.0f, 0.0f, 49 | 0.0f, 1.0f, 50 | 1.0f, 0.0f, 51 | 1.0f, 1.0f 52 | } 53 | }; 54 | 55 | GLfloat cursorVertices[8]; 56 | 57 | Bool hwc_init_hybris_native_buffer(ScrnInfoPtr pScrn) 58 | { 59 | HWCPtr hwc = HWCPTR(pScrn); 60 | hwc_renderer_ptr renderer = &hwc->renderer; 61 | 62 | if (strstr(eglQueryString(renderer->display, EGL_EXTENSIONS), "EGL_HYBRIS_native_buffer") == NULL) 63 | { 64 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "EGL_HYBRIS_native_buffer is missing. Make sure libhybris EGL implementation is used\n"); 65 | return FALSE; 66 | } 67 | 68 | renderer->eglHybrisCreateNativeBuffer = (PFNEGLHYBRISCREATENATIVEBUFFERPROC) eglGetProcAddress("eglHybrisCreateNativeBuffer"); 69 | assert(renderer->eglHybrisCreateNativeBuffer != NULL); 70 | 71 | renderer->eglHybrisLockNativeBuffer = (PFNEGLHYBRISLOCKNATIVEBUFFERPROC) eglGetProcAddress("eglHybrisLockNativeBuffer"); 72 | assert(renderer->eglHybrisLockNativeBuffer != NULL); 73 | 74 | renderer->eglHybrisUnlockNativeBuffer = (PFNEGLHYBRISUNLOCKNATIVEBUFFERPROC) eglGetProcAddress("eglHybrisUnlockNativeBuffer"); 75 | assert(renderer->eglHybrisUnlockNativeBuffer != NULL); 76 | 77 | renderer->eglHybrisReleaseNativeBuffer = (PFNEGLHYBRISRELEASENATIVEBUFFERPROC) eglGetProcAddress("eglHybrisReleaseNativeBuffer"); 78 | assert(renderer->eglHybrisReleaseNativeBuffer != NULL); 79 | 80 | renderer->eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); 81 | assert(renderer->eglCreateImageKHR != NULL); 82 | 83 | renderer->eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR"); 84 | assert(renderer->eglDestroyImageKHR != NULL); 85 | 86 | renderer->glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES"); 87 | assert(renderer->glEGLImageTargetTexture2DOES != NULL); 88 | return TRUE; 89 | } 90 | 91 | void GLAPIENTRY 92 | MessageCallback( GLenum source, 93 | GLenum type, 94 | GLuint id, 95 | GLenum severity, 96 | GLsizei length, 97 | const GLchar* message, 98 | const void* userParam ) 99 | { 100 | fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", 101 | ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), 102 | type, severity, message ); 103 | } 104 | 105 | Bool hwc_egl_renderer_init(ScrnInfoPtr pScrn) 106 | { 107 | HWCPtr hwc = HWCPTR(pScrn); 108 | hwc_renderer_ptr renderer = &hwc->renderer; 109 | 110 | EGLDisplay display; 111 | EGLConfig ecfg; 112 | EGLint num_config; 113 | EGLint attr[] = { // some attributes to set up our egl-interface 114 | EGL_RED_SIZE, 8, 115 | EGL_GREEN_SIZE, 8, 116 | EGL_BLUE_SIZE, 8, 117 | EGL_ALPHA_SIZE, 8, 118 | EGL_DEPTH_SIZE, 24, 119 | EGL_STENCIL_SIZE, 8, 120 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 121 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 122 | EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 123 | EGL_NONE 124 | }; 125 | EGLSurface surface; 126 | EGLint ctxattr[] = { 127 | EGL_CONTEXT_CLIENT_VERSION, 2, 128 | EGL_NONE 129 | }; 130 | EGLContext context; 131 | EGLBoolean rv; 132 | int err; 133 | 134 | struct ANativeWindow *win = hwc_get_native_window(pScrn); 135 | 136 | display = eglGetDisplay(NULL); 137 | assert(eglGetError() == EGL_SUCCESS); 138 | assert(display != EGL_NO_DISPLAY); 139 | renderer->display = display; 140 | 141 | rv = eglInitialize(display, 0, 0); 142 | assert(eglGetError() == EGL_SUCCESS); 143 | assert(rv == EGL_TRUE); 144 | 145 | eglChooseConfig((EGLDisplay) display, attr, &ecfg, 1, &num_config); 146 | assert(eglGetError() == EGL_SUCCESS); 147 | assert(rv == EGL_TRUE); 148 | 149 | surface = eglCreateWindowSurface((EGLDisplay) display, ecfg, (EGLNativeWindowType)win, NULL); 150 | assert(eglGetError() == EGL_SUCCESS); 151 | assert(surface != EGL_NO_SURFACE); 152 | renderer->surface = surface; 153 | 154 | context = eglCreateContext((EGLDisplay) display, ecfg, EGL_NO_CONTEXT, ctxattr); 155 | assert(eglGetError() == EGL_SUCCESS); 156 | assert(context != EGL_NO_CONTEXT); 157 | renderer->context = context; 158 | 159 | assert(eglMakeCurrent((EGLDisplay) display, surface, surface, context) == EGL_TRUE); 160 | 161 | // During init, enable debug output 162 | glEnable ( GL_DEBUG_OUTPUT ); 163 | glDebugMessageCallback( MessageCallback, 0 ); 164 | 165 | 166 | const char *version = glGetString(GL_VERSION); 167 | assert(version); 168 | printf("%s\n",version); 169 | 170 | glGenTextures(1, &renderer->rootTexture); 171 | glGenTextures(1, &renderer->cursorTexture); 172 | renderer->image = EGL_NO_IMAGE_KHR; 173 | renderer->rootShader.program = 0; 174 | renderer->projShader.program = 0; 175 | 176 | return TRUE; 177 | } 178 | 179 | void hwc_egl_renderer_screen_init(ScreenPtr pScreen) 180 | { 181 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 182 | HWCPtr hwc = HWCPTR(pScrn); 183 | hwc_renderer_ptr renderer = &hwc->renderer; 184 | 185 | glBindTexture(GL_TEXTURE_2D, renderer->rootTexture); 186 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 187 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 188 | 189 | if (!hwc->glamor && renderer->image == EGL_NO_IMAGE_KHR) { 190 | renderer->image = renderer->eglCreateImageKHR(renderer->display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_HYBRIS, 191 | (EGLClientBuffer)hwc->buffer, NULL); 192 | renderer->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, renderer->image); 193 | } 194 | 195 | if (!renderer->rootShader.program) { 196 | GLuint prog; 197 | renderer->rootShader.program = prog = 198 | hwc_link_program(vertex_src, hwc->glamor ? fragment_src : fragment_src_bgra); 199 | 200 | if (!prog) { 201 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 202 | "hwc_egl_renderer_screen_init: failed to link root window shader\n"); 203 | } 204 | 205 | renderer->rootShader.position = glGetAttribLocation(prog, "position"); 206 | renderer->rootShader.texcoords = glGetAttribLocation(prog, "texcoords"); 207 | renderer->rootShader.texture = glGetUniformLocation(prog, "texture"); 208 | } 209 | 210 | if (!renderer->projShader.program) { 211 | GLuint prog; 212 | renderer->projShader.program = prog = 213 | hwc_link_program(vertex_mvp_src, hwc->glamor ? fragment_src : fragment_src_bgra); 214 | 215 | if (!prog) { 216 | xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 217 | "hwc_egl_renderer_screen_init: failed to link cursor shader\n"); 218 | } 219 | 220 | renderer->projShader.position = glGetAttribLocation(prog, "position"); 221 | renderer->projShader.texcoords = glGetAttribLocation(prog, "texcoords"); 222 | renderer->projShader.transform = glGetUniformLocation(prog, "transform"); 223 | renderer->projShader.texture = glGetUniformLocation(prog, "texture"); 224 | } 225 | 226 | if (hwc->rotation == HWC_ROTATE_CW || hwc->rotation == HWC_ROTATE_CCW) 227 | hwc_ortho_2d(renderer->projection, 0.0f, pScrn->virtualY, 0.0f, pScrn->virtualX); 228 | else 229 | hwc_ortho_2d(renderer->projection, 0.0f, pScrn->virtualX, 0.0f, pScrn->virtualY); 230 | 231 | eglSwapInterval(renderer->display, 0); 232 | } 233 | 234 | void hwc_translate_cursor(hwc_rotation rotation, int x, int y, int width, int height, 235 | int displayWidth, int displayHeight, 236 | float* vertices) { 237 | int w = displayWidth, h = displayHeight; 238 | int cw = width, ch = height; 239 | int t; 240 | int i = 0; 241 | 242 | #define P(x, y) vertices[i++] = x; vertices[i++] = y; // Point vertex 243 | switch (rotation) { 244 | case HWC_ROTATE_NORMAL: 245 | y = h - y - ch - 1; 246 | 247 | P(x, y); 248 | P(x + cw, y); 249 | P(x, y + ch); 250 | P(x + cw, y + ch); 251 | break; 252 | case HWC_ROTATE_CW: 253 | t = x; 254 | x = h - y - 1; 255 | y = w - t - 1; 256 | 257 | P(x - ch, y - cw); 258 | P(x, y - cw); 259 | P(x - ch, y); 260 | P(x, y); 261 | break; 262 | case HWC_ROTATE_UD: 263 | x = w - x - 1; 264 | 265 | P(x - cw, y); 266 | P(x, y); 267 | P(x - cw, y + ch); 268 | P(x, y + ch); 269 | break; 270 | case HWC_ROTATE_CCW: 271 | t = x; 272 | x = y; 273 | y = t; 274 | 275 | P(x, y); 276 | P(x + ch, y); 277 | P(x, y + cw); 278 | P(x + ch, y + cw); 279 | break; 280 | } 281 | #undef P 282 | } 283 | 284 | void hwc_egl_render_cursor(ScreenPtr pScreen) { 285 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 286 | HWCPtr hwc = HWCPTR(pScrn); 287 | hwc_renderer_ptr renderer = &hwc->renderer; 288 | 289 | glUseProgram(renderer->projShader.program); 290 | 291 | glBindTexture(GL_TEXTURE_2D, renderer->cursorTexture); 292 | glUniform1i(renderer->projShader.texture, 0); 293 | 294 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 295 | glEnable(GL_BLEND); 296 | 297 | hwc_translate_cursor(hwc->rotation, hwc->cursorX, hwc->cursorY, 298 | hwc->cursorWidth, hwc->cursorHeight, 299 | pScrn->virtualX, pScrn->virtualY, 300 | cursorVertices); 301 | 302 | glVertexAttribPointer(renderer->projShader.position, 2, GL_FLOAT, 0, 0, cursorVertices); 303 | glEnableVertexAttribArray(renderer->projShader.position); 304 | 305 | glVertexAttribPointer(renderer->projShader.texcoords, 2, GL_FLOAT, 0, 0, textureVertices[hwc->rotation]); 306 | glEnableVertexAttribArray(renderer->projShader.texcoords); 307 | 308 | glUniformMatrix4fv(renderer->projShader.transform, 1, GL_FALSE, renderer->projection); 309 | 310 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 311 | 312 | glDisable(GL_BLEND); 313 | glDisableVertexAttribArray(renderer->projShader.position); 314 | glDisableVertexAttribArray(renderer->projShader.texcoords); 315 | } 316 | 317 | void hwc_egl_renderer_update(ScreenPtr pScreen) 318 | { 319 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 320 | HWCPtr hwc = HWCPTR(pScrn); 321 | hwc_renderer_ptr renderer = &hwc->renderer; 322 | 323 | if (hwc->glamor) { 324 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 325 | glViewport(0, 0, hwc->hwcWidth, hwc->hwcHeight); 326 | } 327 | 328 | glUseProgram(renderer->rootShader.program); 329 | 330 | glActiveTexture(GL_TEXTURE0); 331 | glBindTexture(GL_TEXTURE_2D, renderer->rootTexture); 332 | glUniform1i(renderer->rootShader.texture, 0); 333 | 334 | glVertexAttribPointer(renderer->rootShader.position, 2, GL_FLOAT, 0, 0, squareVertices); 335 | glEnableVertexAttribArray(renderer->rootShader.position); 336 | 337 | glVertexAttribPointer(renderer->rootShader.texcoords, 2, GL_FLOAT, 0, 0, textureVertices[hwc->rotation]); 338 | glEnableVertexAttribArray(renderer->rootShader.texcoords); 339 | 340 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 341 | 342 | glDisableVertexAttribArray(renderer->rootShader.position); 343 | glDisableVertexAttribArray(renderer->rootShader.texcoords); 344 | 345 | if (hwc->cursorShown) 346 | hwc_egl_render_cursor(pScreen); 347 | 348 | eglSwapBuffers (renderer->display, renderer->surface ); // get the rendered buffer to the screen 349 | } 350 | 351 | void hwc_egl_renderer_screen_close(ScreenPtr pScreen) 352 | { 353 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 354 | HWCPtr hwc = HWCPTR(pScrn); 355 | hwc_renderer_ptr renderer = &hwc->renderer; 356 | 357 | if (renderer->image != EGL_NO_IMAGE_KHR) { 358 | renderer->eglDestroyImageKHR(renderer->display, renderer->image); 359 | renderer->image = EGL_NO_IMAGE_KHR; 360 | } 361 | } 362 | 363 | void hwc_egl_renderer_close(ScrnInfoPtr pScrn) 364 | { 365 | } 366 | -------------------------------------------------------------------------------- /src/shaders.c: -------------------------------------------------------------------------------- 1 | const char vertex_src [] = 2 | "attribute vec4 position;\n" 3 | "attribute vec4 texcoords;\n" 4 | "varying vec2 textureCoordinate;\n" 5 | 6 | "void main()\n" 7 | "{\n" 8 | " gl_Position = position;\n" 9 | " textureCoordinate = texcoords.xy;\n" 10 | "}\n"; 11 | 12 | const char vertex_mvp_src [] = 13 | "attribute vec2 position;\n" 14 | "attribute vec2 texcoords;\n" 15 | "varying vec2 textureCoordinate;\n" 16 | "uniform mat4 transform;\n" 17 | 18 | "void main()\n" 19 | "{\n" 20 | " gl_Position = transform * vec4(position, 0.0, 1.0);\n" 21 | " textureCoordinate = texcoords.xy;\n" 22 | "}\n"; 23 | 24 | const char fragment_src [] = 25 | "varying highp vec2 textureCoordinate;\n" 26 | "uniform sampler2D texture;\n" 27 | 28 | "void main()\n" 29 | "{\n" 30 | " gl_FragColor = texture2D(texture, textureCoordinate);\n" 31 | "}\n"; 32 | 33 | const char fragment_src_bgra [] = 34 | "varying highp vec2 textureCoordinate;\n" 35 | "uniform sampler2D texture;\n" 36 | 37 | "void main()\n" 38 | "{\n" 39 | " gl_FragColor = texture2D(texture, textureCoordinate).bgra;\n" 40 | "}\n"; 41 | --------------------------------------------------------------------------------