From 7725e18ca342503d7a0c39ce9ff3a0486a7b5ce6 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:37:29 -0800 Subject: [PATCH] libcopybit: Add copybit and copybit_c2d changes from Gingerbread Change-Id: I39ccc7579f89d08eae809b47e434601aee6973a2 --- libcopybit/Android.mk | 67 ++- libcopybit/c2d2.h | 618 ++++++++++++++++++++++ libcopybit/copybit.cpp | 78 +-- libcopybit/copybit_c2d.cpp | 1008 ++++++++++++++++++++++++++++++++++++ 4 files changed, 1717 insertions(+), 54 deletions(-) create mode 100644 libcopybit/c2d2.h create mode 100644 libcopybit/copybit_c2d.cpp diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index 36b1416..a19de13 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -17,26 +17,51 @@ LOCAL_PATH:= $(call my-dir) # HAL module implemenation, not prelinked and stored in # hw/..so -ifeq ($(TARGET_BOARD_PLATFORM),msm7k) -include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog -LOCAL_SRC_FILES := copybit.cpp -LOCAL_MODULE := copybit.msm7k -LOCAL_C_INCLUDES += hardware/msm7k/libgralloc -LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1 -include $(BUILD_SHARED_LIBRARY) -endif +ifeq ($(TARGET_USES_C2D_COMPOSITION),true) + include $(CLEAR_VARS) + LOCAL_PRELINK_MODULE := false + LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + LOCAL_SHARED_LIBRARIES := liblog libdl + LOCAL_SRC_FILES := copybit_c2d.cpp + LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM) + LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k + LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1 + include $(BUILD_SHARED_LIBRARY) +else + ifneq "$(findstring msm7630,$(TARGET_PRODUCT))" "msm7630" + ifeq ($(TARGET_BOARD_PLATFORM),msm7k) + include $(CLEAR_VARS) + ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true) + LOCAL_CFLAGS += -DUSE_ASHMEM + ifeq "$(findstring msm7627,$(TARGET_PRODUCT))" "msm7627" + LOCAL_CFLAGS += -DTARGET_7x27 + endif + endif -ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) -include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog -LOCAL_SRC_FILES := copybit.cpp -LOCAL_MODULE := copybit.qsd8k -LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc -LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 -include $(BUILD_SHARED_LIBRARY) + LOCAL_PRELINK_MODULE := false + LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + LOCAL_SHARED_LIBRARIES := liblog + LOCAL_SRC_FILES := copybit.cpp + LOCAL_MODULE := copybit.msm7k + LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k + LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1 + include $(BUILD_SHARED_LIBRARY) + endif + + ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) + include $(CLEAR_VARS) + ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true) + LOCAL_CFLAGS += -DUSE_ASHMEM + endif + + LOCAL_PRELINK_MODULE := false + LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + LOCAL_SHARED_LIBRARIES := liblog + LOCAL_SRC_FILES := copybit.cpp + LOCAL_MODULE := copybit.qsd8k + LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k + LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 + include $(BUILD_SHARED_LIBRARY) + endif + endif endif diff --git a/libcopybit/c2d2.h b/libcopybit/c2d2.h new file mode 100644 index 0000000..10c94be --- /dev/null +++ b/libcopybit/c2d2.h @@ -0,0 +1,618 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __c2d2_h_ +#define __c2d2_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include /* for EGL surfaces */ + +#ifndef C2D_API +#define C2D_API /* define API export as needed */ +#endif +#ifndef int32 +typedef int int32; +#endif +#ifndef uint32 +typedef unsigned int uint32; +#endif + +/*****************************************************************************/ +/*********************** Blit definitions *****************************/ +/*****************************************************************************/ + +/* Status codes, returned by any blit function */ +typedef enum { + C2D_STATUS_OK = 0, + C2D_STATUS_NOT_SUPPORTED = 1, + C2D_STATUS_OUT_OF_MEMORY = 2, + C2D_STATUS_INVALID_PARAM = 3, + C2D_STATUS_SURFACE_IN_USE = 4, +} C2D_STATUS; + + +/* Definitions of color format modes, used together with color formats */ +typedef enum { + C2D_FORMAT_PACK_INTO_32BIT = (1 << 8), /* pack into dword if set */ + C2D_FORMAT_SWAP_ENDIANNESS = (1 << 9), /* swaps the order */ + C2D_FORMAT_LINEAR_SPACE = (1 << 10), /* linear color space */ + C2D_FORMAT_PREMULTIPLIED = (1 << 11), /* alpha premultiplied */ + C2D_FORMAT_INVERT_ALPHA = (1 << 12), /* inverts alpha */ + C2D_FORMAT_DISABLE_ALPHA = (1 << 13), /* disables alpha */ + C2D_FORMAT_INTERLACED = (1 << 14), /* YUV line-interlaced */ + C2D_FORMAT_TRANSPARENT = (1 << 15), /* YUV 1-bit alpha in Y */ + C2D_FORMAT_MACROTILED = (1 << 16), /* tiled in macro level */ + C2D_FORMAT_TILED_4x4 = (1 << 17), /* 4x4 tiled format */ + C2D_FORMAT_SWAP_RB = (1 << 18), /* Swap R & B color components */ +} C2D_FORMAT_MODE; + +/* Definitions of supported RGB formats, used in C2D_RGB_SURFACE_DEF. + * The bits of each color channel are packed into a machine word + * representing a single pixel from left to right (MSB to LSB) in the + * order indicated by format name. For the sub-byte formats the pixels + * are packed into bytes from left to right (MSbit to LSBit). + * If the C2D_FORMAT_PACK_INTO_32BIT bit is set, the minimal + * machine word used for pixel storage is 32-bit and the whole word + * is reversed if endianness is swapped. + * If the C2D_FORMAT_SWAP_ENDIANNESS bit is set, the order within a + * minimal machine word representing a pixel + * is reversed for both sub-byte and multi-byte formats. + * If the C2D_FORMAT_LINEAR_SPACE bit is set, the color space of + * the formats below is considered linear, if applicable. + * If the C2D_FORMAT_PREMULTIPLIED bit is set, the color channels + * are premultiplied with the alpha, if applicable. + * If the C2D_FORMAT_INVERT_ALPHA bit is set, the alpha interpretation + * is inverted: 0 - opaque, 1 - transparent, if applicable. + * If the C2D_FORMAT_DISABLE_ALPHA bit is set, the alpha channel serves + * as a placeholder and is ignored during blit, if applicable. + * If the COMP_FORMAT_MACROTILED bit is set, the surface is in the + * tiled format : 64x32 for 8bpp, 32x32 for 16bpp formats */ +typedef enum { + C2D_COLOR_FORMAT_1 = 0, /* 1-bit alpha/color expansion */ + + C2D_COLOR_FORMAT_2_PALETTE = 1, /* 2-bit indices for palette */ + C2D_COLOR_FORMAT_4_PALETTE = 2, /* 4-bit indices for palette */ + C2D_COLOR_FORMAT_8_PALETTE = 3, /* 8-bit indices for palette */ + + C2D_COLOR_FORMAT_2_L = 4, /* 2-bit grayscale */ + C2D_COLOR_FORMAT_4_L = 5, /* 4-bit grayscale */ + C2D_COLOR_FORMAT_8_L = 6, /* 8-bit grayscale */ + + C2D_COLOR_FORMAT_2_A = 7, /* 2-bit alpha only */ + C2D_COLOR_FORMAT_4_A = 8, /* 4-bit alpha only */ + C2D_COLOR_FORMAT_8_A = 9, /* 8-bit alpha only */ + + C2D_COLOR_FORMAT_444_RGB = 10, /* 12-bit colors */ + C2D_COLOR_FORMAT_565_RGB = 11, /* 16-bit colors */ + C2D_COLOR_FORMAT_888_RGB = 12, /* 24-bit colors */ + + C2D_COLOR_FORMAT_1555_ARGB = 13, /* 16-bit colors (1-bit alpha) */ + C2D_COLOR_FORMAT_4444_ARGB = 14, /* 16-bit colors (4-bit alpha) */ + C2D_COLOR_FORMAT_8565_ARGB = 15, /* 24-bit colors (8-bit alpha) */ + C2D_COLOR_FORMAT_8888_ARGB = 16, /* 32-bit colors (8-bit alpha) */ + + C2D_COLOR_FORMAT_5551_RGBA = 17, /* 16-bit colors (1-bit alpha) */ + C2D_COLOR_FORMAT_4444_RGBA = 18, /* 16-bit colors (4-bit alpha) */ + C2D_COLOR_FORMAT_5658_RGBA = 19, /* 24-bit colors (8-bit alpha) */ + C2D_COLOR_FORMAT_8888_RGBA = 20, /* 32-bit colors (8-bit alpha) */ + + /* derived RGB color formats (base format + mode bits) */ + +} C2D_RGB_FORMAT; + +/* Definitions of supported YUV formats, used in C2D_YUV_SURFACE_DEF. + * Each of Y,U,V channels usually takes 1 byte and therefore is + * individually addressable. The definitions below show how Y,U,V + * channels are packed into macropixels for each particular format. + * The order is from left (smaller byte addresses) to right (larger + * byte addresses). The first three digits (4xx) denote the chroma + * subsampling in standard YUV notation. The digits in the macropixel + * denote that the whole block (from the previous digit or from the + * beginning) has to be repeated the number of times. Underscores + * between Y,U,V channels are used to describe separate planes for + * planar YUV formats. Formats are mapped to numbers so that future + * versions with various YUV permutations are easy to add. + * If the C2D_FORMAT_INTERLACED bit is set, the line order is + * interlaced: 0,2,4,...1,3,5... if applicable. + * If the C2D_FORMAT_TRANSPARENT bit is set, the least significant + * bit of Y channel serves as alpha: 0 - transparent, 1 - opaque. */ +typedef enum { + C2D_COLOR_FORMAT_411_YYUYYV = 110, /* packed, 12-bit */ + C2D_COLOR_FORMAT_411_YUYYVY = 111, /* packed, 12-bit */ + C2D_COLOR_FORMAT_411_UYYVYY = 112, /* packed, 12-bit, "Y411" */ + C2D_COLOR_FORMAT_411_YUYV2Y4 = 116, /* packed, 12-bit */ + C2D_COLOR_FORMAT_411_UYVY2Y4 = 117, /* packed, 12-bit, "Y41P" */ + + C2D_COLOR_FORMAT_422_YUYV = 120, /* packed, 16-bit, "YUY2" */ + C2D_COLOR_FORMAT_422_UYVY = 121, /* packed, 16-bit, "UYVY" */ + C2D_COLOR_FORMAT_422_YVYU = 122, /* packed, 16-bit, "YVYU" */ + C2D_COLOR_FORMAT_422_VYUY = 123, /* packed, 16-bit */ + + C2D_COLOR_FORMAT_444_YUV = 130, /* packed, 24-bit */ + C2D_COLOR_FORMAT_444_UYV = 131, /* packed, 24-bit, "IYU2" */ + C2D_COLOR_FORMAT_444_AYUV = 136, /* packed, 24-bit, "AYUV" */ + + C2D_COLOR_FORMAT_410_Y_UV = 150, /* planar, Y + interleaved UV */ + C2D_COLOR_FORMAT_411_Y_UV = 151, /* planar, Y + interleaved UV */ + C2D_COLOR_FORMAT_420_Y_UV = 152, /* planar, Y + interleaved UV */ + C2D_COLOR_FORMAT_422_Y_UV = 153, /* planar, Y + interleaved UV */ + C2D_COLOR_FORMAT_444_Y_UV = 154, /* planar, Y + interleaved UV */ + + C2D_COLOR_FORMAT_410_Y_VU = 160, /* planar, Y + interleaved VU */ + C2D_COLOR_FORMAT_411_Y_VU = 161, /* planar, Y + interleaved VU */ + C2D_COLOR_FORMAT_420_Y_VU = 162, /* planar, Y + interleaved VU */ + C2D_COLOR_FORMAT_422_Y_VU = 163, /* planar, Y + interleaved VU */ + C2D_COLOR_FORMAT_444_Y_VU = 164, /* planar, Y + interleaved VU */ + + C2D_COLOR_FORMAT_410_Y_U_V = 170, /* planar, Y + U + V separate */ + C2D_COLOR_FORMAT_411_Y_U_V = 171, /* planar, Y + U + V separate */ + C2D_COLOR_FORMAT_420_Y_V_U = 172, /* planar, Y + V + U separate */ + C2D_COLOR_FORMAT_420_Y_U_V = 173, /* planar, Y + U + V separate */ + C2D_COLOR_FORMAT_422_Y_U_V = 174, /* planar, Y + U + V separate */ + C2D_COLOR_FORMAT_444_Y_U_V = 175, /* planar, Y + U + V separate */ + + C2D_COLOR_FORMAT_800_Y = 190, /* planar, Y only, grayscale */ + + /* derived YUV color formats (base format + mode bits), FOURCC */ + + C2D_COLOR_FORMAT_411_Y411 = 112, + C2D_COLOR_FORMAT_411_Y41P = 117, + C2D_COLOR_FORMAT_411_IY41 = 117 | (1 << 14), + C2D_COLOR_FORMAT_411_Y41T = 117 | (1 << 15), + + C2D_COLOR_FORMAT_422_YUY2 = 120, + C2D_COLOR_FORMAT_422_IUYV = 121 | (1 << 14), + C2D_COLOR_FORMAT_422_Y42T = 121 | (1 << 15), + C2D_COLOR_FORMAT_444_IYU2 = 131, + + C2D_COLOR_FORMAT_420_NV12 = 152, + C2D_COLOR_FORMAT_420_NV21 = 162, + + C2D_COLOR_FORMAT_410_YUV9 = 170, + C2D_COLOR_FORMAT_410_YVU9 = 170, + C2D_COLOR_FORMAT_411_Y41B = 171, + C2D_COLOR_FORMAT_420_YV12 = 172, + C2D_COLOR_FORMAT_420_IYUV = 173, + C2D_COLOR_FORMAT_420_I420 = 173, + C2D_COLOR_FORMAT_422_YV16 = 174, + C2D_COLOR_FORMAT_422_Y42B = 174, + + C2D_COLOR_FORMAT_800_Y800 = 190, + +} C2D_YUV_FORMAT; + + +/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */ +typedef enum { + C2D_SOURCE_RECT_BIT = (1 << 0), /* enables source_rect field */ + C2D_MIRROR_H_BIT = (1 << 1), /* enables horizontal flipping */ + C2D_MIRROR_V_BIT = (1 << 2), /* enables vertical flipping */ + C2D_SOURCE_TILE_BIT = (1 << 3), /* enables source surface tiling */ + C2D_TARGET_RECT_BIT = (1 << 4), /* enables target_rect field */ + C2D_ROTATE_BIT = (1 << 5), /* enables all rotation fields */ + C2D_SCISSOR_RECT_BIT = (1 << 6), /* enables scissor_rect field */ + C2D_MASK_SURFACE_BIT = (1 << 7), /* enables mask_surface_id field */ + C2D_MASK_ALIGN_BIT = (1 << 8), /* aligns mask to source_rect */ + C2D_MASK_SCALE_BIT = (1 << 9), /* enables mask surface scaling */ + C2D_MASK_TILE_BIT = (1 << 10), /* enables mask surface tiling */ + C2D_GLOBAL_ALPHA_BIT = (1 << 11), /* enables global_alpha field */ + C2D_COLOR_KEY_BIT = (1 << 12), /* enables color_key field */ + C2D_NO_PIXEL_ALPHA_BIT = (1 << 13), /* disables source alpha channel */ + C2D_NO_BILINEAR_BIT = (1 << 14), /* disables bilinear on scaling */ + C2D_NO_ANTIALIASING_BIT = (1 << 15), /* disables antialiasing on edges */ + C2D_DRAW_LINE_BIT = (1 << 16), /* enables line drawing with source rectangle */ + C2D_DRAW_LINE_NOLAST = (1 << 17), /* disable last pixel draw for line */ +} C2D_SOURCE_CONFIG; + +/* Target configuration bits, defines rotation + mirroring. + * Mirror is applied prior to rotation if enabled. */ +typedef enum { + C2D_TARGET_MIRROR_H = (1 << 0), /* horizontal flip */ + C2D_TARGET_MIRROR_V = (1 << 1), /* vertical flip */ + C2D_TARGET_ROTATE_0 = (0 << 2), /* no rotation */ + C2D_TARGET_ROTATE_90 = (1 << 2), /* 90 degree rotation */ + C2D_TARGET_ROTATE_180 = (2 << 2), /* 180 degree rotation */ + C2D_TARGET_ROTATE_270 = (3 << 2), /* 270 degree rotation, 90 + 180 */ + C2D_TARGET_MASK_ALIGN = (1 << 4), /* aligns mask to target scissor */ + C2D_TARGET_MASK_SCALE = (1 << 5), /* enables mask scaling */ + C2D_TARGET_MASK_TILE = (1 << 6), /* enables mask tiling */ + C2D_TARGET_COLOR_KEY = (1 << 7), /* enables target_color_key */ + C2D_TARGET_NO_PIXEL_ALPHA = (1 << 8), /* disables target alpha channel */ +} C2D_TARGET_CONFIG; + +#define C2D_TARGET_ROTATION_MASK (C2D_TARGET_ROTATE_90*3) + +/* Additional blend modes, can be used with both source and target configs. + If none of the below is set, the default "SRC over DST" is applied. */ +typedef enum { + C2D_ALPHA_BLEND_SRC_OVER = (0 << 20), /* Default, Porter-Duff "SRC over DST" */ + C2D_ALPHA_BLEND_SRC = (1 << 20), /* Porter-Duff "SRC" */ + C2D_ALPHA_BLEND_SRC_IN = (2 << 20), /* Porter-Duff "SRC in DST" */ + C2D_ALPHA_BLEND_DST_IN = (3 << 20), /* Porter-Duff "DST in SRC" */ + C2D_ALPHA_BLEND_SRC_OUT = (4 << 20), /* Porter-Duff "SRC out DST" */ + C2D_ALPHA_BLEND_DST_OUT = (5 << 20), /* Porter-Duff "DST out SRC" */ + C2D_ALPHA_BLEND_DST_OVER = (6 << 20), /* Porter-Duff "DST over SRC" */ + C2D_ALPHA_BLEND_SRC_ATOP = (7 << 20), /* Porter-Duff "SRC ATOP" */ + C2D_ALPHA_BLEND_DST_ATOP = (8 << 20), /* Porter-Duff "DST ATOP" */ + C2D_ALPHA_BLEND_XOR = (9 << 20), /* Xor */ + C2D_ALPHA_BLEND_MULTIPLY = (10 << 20), /* OpenVG "MULTIPLY" */ + C2D_ALPHA_BLEND_SCREEN = (11 << 20), /* OpenVG "SCREEN" */ + C2D_ALPHA_BLEND_DARKEN = (12 << 20), /* OpenVG "DARKEN" */ + C2D_ALPHA_BLEND_LIGHTEN = (13 << 20), /* OpenVG "LIGHTEN" */ + C2D_ALPHA_BLEND_ADDITIVE = (14 << 20), /* OpenVG "ADDITIVE" */ + C2D_ALPHA_BLEND_DIRECT = (15 << 20), /* Direct alpha blitting */ + C2D_ALPHA_BLEND_INVERTC = (16 << 20), /* Invert color */ + C2D_ALPHA_BLEND_NONE = (1 << 25), /* disables alpha blending */ +} C2D_ALPHA_BLEND_MODE; + + +/* Surface caps enumeration */ +typedef enum { + C2D_SOURCE = (1 << 0), /* allows to use as a source */ + C2D_TARGET = (1 << 1), /* allows to use as a target */ + C2D_MASK = (1 << 2), /* allows to use as a mask */ + C2D_PALETTE = (1 << 3), /* allows to use as a palette */ +} C2D_SURFACE_BITS; + +/* Surface type enumeration */ +typedef enum { + C2D_SURFACE_EGL = 0, /* Arbitrary EGL surface */ + C2D_SURFACE_RGB_HOST = 1, /* Host memory RGB surface */ + C2D_SURFACE_RGB_EXT = 2, /* External memory RGB surface */ + C2D_SURFACE_YUV_HOST = 3, /* Host memory YUV surface */ + C2D_SURFACE_YUV_EXT = 4, /* External memory YUV surface */ + C2D_SURFACE_WITH_PHYS = (1<<3), /* physical address allready mapped */ + /* this bit is valid with HOST types */ +} C2D_SURFACE_TYPE; + +/* Structure for registering an EGL surface as a blit surface */ +typedef struct { + EGLDisplay display; /* EGL display */ + EGLContext context; /* EGL context, reserved - pass EGL_NO_CONTEXT */ + EGLSurface surface; /* EGL surface */ +} C2D_EGL_SURFACE_DEF; + +/* Structure for registering a RGB buffer as a blit surface */ +typedef struct { + uint32 format; /* RGB color format plus additional mode bits */ + uint32 width; /* defines width in pixels */ + uint32 height; /* defines height in pixels */ + void *buffer; /* pointer to the RGB buffer */ + void *phys; /* physical address */ + int32 stride; /* defines stride in bytes, negative stride is allowed */ +} C2D_RGB_SURFACE_DEF; + +/* Structure for registering a YUV plane(s) as a blit surface */ +typedef struct { + uint32 format; /* YUV color format plus additional mode bits */ + uint32 width; /* defines width in pixels */ + uint32 height; /* defines height in pixels */ + void *plane0; /* holds the whole buffer if YUV format is not planar */ + void *phys0; /* physical address */ + int32 stride0; /* stride in bytes if YUV format is not planar */ + void *plane1; /* holds UV or VU plane for planar interleaved */ + void *phys1; /* physical address */ + int32 stride1; /* stride for UV or VU plane for planar interleaved */ + void *plane2; /* holds the 3. plane, ignored if YUV format is not planar */ + void *phys2; /* physical address */ + int32 stride2; /* stride for the 3. plane, ignored if YUV format is not planar */ +} C2D_YUV_SURFACE_DEF; + + +/* Rectangle definition */ +typedef struct { + int32 x; /* upper-left x */ + int32 y; /* upper-left y */ + int32 width; /* width */ + int32 height; /* height */ +} C2D_RECT; + +/* C2D_OBJECT encapsulates the blit parameters for a source surface. + * The fg_color defines color in target format for bits equal to 1 + * in the source C2D_COLOR_FORMAT_1 format. It also defines rendering + * color for all alpha-only source formats. If the surface_id is 0 + * the fg_color defines a constant fill color used instead of the surface. + * The bg_color defines color in target format for bits equal to 0 + * in the source C2D_COLOR_FORMAT_1 format, otherwise both are ignored. + * The palette_id is used for all palette source formats, otherwise ignored. + + * The source_rect first defines the content of the source surface, + * it is then horizontally/vertically flipped if C2D_MIRROR_*_BIT is set, + * then scaled with bilinear interpolation to exactly fit target_rect + * or repeated across target_rect if C2D_SOURCE_TILE_BIT is set, + * target_rect is then rotated clockwise by an arbitrary angle in degrees + * around the rot_orig_x/y, defined relative to target_rect's top left point, + * and then clipped to scissor_rect defined in target coordinate system. + + * Finally alpha blending is applied before pixels get written into the target. + * Surface's pixel alpha is combined with mask alpha and with global alpha. + * Mask surface follows all transformations applied to the source surface. + * Source color key defines transparent color, applied together with alpha. */ +typedef struct C2D_OBJECT_STR { + uint32 surface_id; /* source surface */ + + uint32 fg_color; /* foreground color */ + uint32 bg_color; /* background color */ + uint32 palette_id; /* one-dimensional horizontal palette surface */ + + uint32 config_mask; /* defines which fields below are enabled */ + + C2D_RECT source_rect; /* region of the source surface, 16.16 fp */ + C2D_RECT target_rect; /* position and scaling in target, 16.16 fp */ + + int32 rot_orig_x; /* rotation origin relative to target_rect's... */ + int32 rot_orig_y; /* ...top left point, both are 16.16 fp */ + int32 rotation; /* clock-wise rotation in degrees, 16.16 fp */ + + C2D_RECT scissor_rect; /* defines the clip rectangle in target surface */ + + uint32 mask_surface_id; /* source alpha-mask surface */ + uint32 global_alpha; /* 0 = fully transparent, 255 = fully opaque */ + uint32 color_key; /* transparent color for the source surface */ + + struct C2D_OBJECT_STR *next; /* pointer to the next object or NULL */ +} C2D_OBJECT; + + +/*****************************************************************************/ +/**************************** C2D API 2.0 ********************************/ +/*****************************************************************************/ + +/****************************************************************************** + * Functions to create/destroy surfaces */ + +/* Creates a generic blit surface according to its type. + * Pass a combination of desired surface bits according to planned usage. + * Accepted values for surface_bits may include bits from C2D_SURFACE_BITS, + * and also from C2D_DISPLAY for compatibility with HW display controller. + * For host memory types the memory is preallocated outside the API + * and should remain valid until surface is destroyed. + * For external memory types the memory is allocated within API. + * On success, the non-zero surface identifier is returned. + * All numbers greater that 0 are valid surface identifiers, 0 is invalid. + + * arbitrary EGL surface (including proprietary Command List Surface): + * surface_type = C2D_SURFACE_EGL + * surface_definition = C2D_EGL_SURFACE_DEF + * all fields in definition structure should be set + * context field is reserved and can be ignored + + * Host memory RGB surface: + * surface_type = C2D_SURFACE_RGB_HOST + * surface_definition = C2D_RGB_SURFACE_DEF + * all fields in definition structure should be set + + * External memory RGB surface: + * surface_type = C2D_SURFACE_RGB_EXT + * surface_definition = C2D_RGB_SURFACE_DEF + * buffer field in definition structure is ignored + + * Host memory YUV surface: + * surface_type = C2D_SURFACE_YUV_HOST + * surface_definition = C2D_YUV_SURFACE_DEF + * one or all plane and stride fields in definition structure + * should be set depending on whether the format is planar or not + + * External memory YUV surface: + * surface_type = C2D_SURFACE_YUV_EXT + * surface_definition = C2D_YUV_SURFACE_DEF + * all plane and stride fields in definition structure are ignored */ +C2D_API C2D_STATUS c2dCreateSurface( uint32 *surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +/* Requests properties of the specified surface. */ +C2D_API C2D_STATUS c2dQuerySurface( uint32 surface_id, + uint32 *surface_bits, + C2D_SURFACE_TYPE *surface_type, + uint32 *width, uint32 *height, + uint32 *format ); + +/* Destroys a generic blit surface. + * For external memory surfaces also deallocates the memory. + * It is safe to free any external resources associated with a given + * surface on c2dCreateSurface call after this function returns. */ +C2D_API C2D_STATUS c2dDestroySurface( uint32 surface_id ); + + +/****************************************************************************** + * Functions to modify/exchange surface data */ + +/* The format of fill_color is the same as color format being used + * for specified surface. If fill_rect is NULL the whole surface is filled. + * Alpha-blending is not performed while filling. + * The operation is complete when function returns. */ +C2D_API C2D_STATUS c2dFillSurface( uint32 surface_id, + uint32 fill_color, + C2D_RECT *fill_rect ); + +/* Writes data located in host memory into the specified surface. + * The chunk of host memory is identified with surface_type and + * surface_definition, no surface registration needed in this case. + * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted. + * If only part of the host memory buffer should be loaded, it should + * be configured in surface_definition using width, height and stride. + * The x and y are defined in target surface coordinate space. + * Color conversion has to be done, if color formats differ. + * Alpha-blending is not performed while writing. + * The operation is complete when function returns. */ +C2D_API C2D_STATUS c2dWriteSurface( uint32 surface_id, + C2D_SURFACE_TYPE surface_type, + void *surface_definition, + int32 x, int32 y ); + +/* Reads data from the specified surface into the host memory. + * The chunk of host memory is identified with surface_type and + * surface_definition, no surface registration needed in this case. + * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted. + * If only part of the surface should be read, it should + * be configured in surface_definition using width, height and stride. + * The x and y are defined in source surface coordinate space. + * Color conversion has to be done, if color formats differ. + * Alpha-blending is not performed while reading. + * The operation is complete when function returns. */ +C2D_API C2D_STATUS c2dReadSurface( uint32 surface_id, + C2D_SURFACE_TYPE surface_type, + void *surface_definition, + int32 x, int32 y ); + +/* Notifies c2d imlementation that surface has been updated from outside the API, + * if updated_rect is NULL then the whole surface has been updated. */ +C2D_API C2D_STATUS c2dSurfaceUpdated( uint32 surface_id, + C2D_RECT *updated_rect ); + +/* Updates surface information. + * Could be called only for host surfaces set with parameter "C2D_SURFACE_WITH_PHYS". + * Count for surface planes have to be same than for already allocated surface */ +C2D_API C2D_STATUS c2dUpdateSurface( uint32 surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +/****************************************************************************** + * Functions to do actual blit */ + +/* Draw a list of blit objects into the given target. + * The target_config is a bitwise OR of values from C2D_TARGET_CONFIG. + * The target transformation creates the effect that target surface + * is transformed before the blit and then transformed back + * after blit, however no physical target transform is performed. + * The objects_list is a linked list of blit objects, no more + * than num_objects is drawn from the given list. + * If num_objects is 0, the whole list is drawn. + * The blit is not guaranteed to complete after function returns. */ +C2D_API C2D_STATUS c2dDraw( uint32 target_id, + uint32 target_config, C2D_RECT *target_scissor, + uint32 target_mask_id, uint32 target_color_key, + C2D_OBJECT *objects_list, uint32 num_objects ); + + +/* timstamp set in the blit commands flush */ +typedef void* c2d_ts_handle; + +/* Forces any pending blit to complete for a given target. + * Non-blocking. All input surfaces for this target except those + * which are shared with other targets are expected to be immediately + * writable after client has been waiting returned timestamp with + * c2dWaitTimestamp funtion or c2dFinish has been called for same target */ +C2D_API C2D_STATUS c2dFlush( uint32 target_id, c2d_ts_handle *timestamp); + + +/* Waits the pending timestamp */ +C2D_API C2D_STATUS c2dWaitTimestamp( c2d_ts_handle timestamp ); + + +/* Forces any pending blit to complete for a given target. + * Blocking version, returns when blit is done. + * All input surfaces for this target except those which are shared with + * other targets are expected to be immediately + * writable after this function returns. */ +C2D_API C2D_STATUS c2dFinish( uint32 target_id ); + + +/*****************************************************************************/ +/****************************** Display API **********************************/ +/*****************************************************************************/ + + +/* Display input enumeration */ +typedef enum { + C2D_DISPLAY_INPUT_0 = 0, /*!< default input */ + C2D_DISPLAY_INPUT_1 = (1<<16), /*!< Overlay 1 */ + C2D_DISPLAY_INPUT_2 = (1<<17), /*!< Overlay 2... */ +} C2D_DISPLAY_INPUT; + + +/****************************************************************************** + * Functions for display output. */ + +/* Functionality described in this section is optional and is + * provided only for the cases when blit HW + * is tightly bound to the display controller. */ + +/* Display enumeration, may also be used in surface caps */ +typedef enum { + C2D_DISPLAY_MAIN = (1 << 10), /* main display */ + C2D_DISPLAY_SECONDARY = (1 << 11), /* secondary display */ + C2D_DISPLAY_TV_OUT = (1 << 12), /* tv-out */ +} C2D_DISPLAY; + +/* Display window enumeration */ +typedef enum { + C2D_DISPLAY_OVERLAY = C2D_DISPLAY_INPUT_1, /*!< Overlay window bit. This defines display input. + When defined the surface is set on the overlay window + otherwise the surface is set on the background window. */ +} C2D_DISPLAY_WINDOW; /*!< Window bit set with display parameter */ + + +/* Display update modes */ +typedef enum { + C2D_DISPLAY_MODE_TEAR_SYNC = (1 << 0), /* enables tearing sync */ + C2D_DISPLAY_MODE_SURF_REMOVE = (1 << 1), /* Remove surface from given display + input */ +} C2D_DISPLAY_MODE; + + +/* Sets the given surface as a current display front buffer. + * Several displays can be specified as an output if supported. + * Still only one input can be specified at a time fro display/displays. + * The surface remains shown until it gets replaced with another one. */ +C2D_API C2D_STATUS c2dDisplaySetSurface( uint32 display, + uint32 surface_id, uint32 mode ); + +/* Returns the current surface for a particular display. + * Only one display can be specified at a time. + * The latest surface set with compDisplaySetSurface or + * the default pre-allocated surface is returned. */ +C2D_API C2D_STATUS c2dDisplayGetSurface( uint32 display, + uint32 *surface_id ); + +/* Returns the properties for a particular display. + * Only one display can be specified at a time. */ +C2D_API C2D_STATUS c2dDisplayGetProperties( uint32 display, + uint32 *width, uint32 *height, + uint32 *format ); + +/* Sets the properties for a particular display input. + * Only one display + input can be specified at a time. + * C2D_OBJECT used to set input rect(target rect), + * blending operations, rotation...etc for display source */ +C2D_API C2D_STATUS c2dDisplaySetObject( uint32 display, + uint32 target_config, uint32 target_color_key, + C2D_OBJECT * c2dObject, uint32 mode); + +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* __c2d2_h_ */ diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 7130ca7..767b3ee 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -119,13 +119,15 @@ static void intersect(struct copybit_rect_t *out, /** convert COPYBIT_FORMAT to MDP format */ static int get_format(int format) { switch (format) { - case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; - case COPYBIT_FORMAT_RGBX_8888: return MDP_RGBX_8888; - case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; - case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; - case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; - case COPYBIT_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2; - case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1; + case HAL_PIXEL_FORMAT_RGB_565: return MDP_RGB_565; + case HAL_PIXEL_FORMAT_RGBX_8888: return MDP_RGBX_8888; + case HAL_PIXEL_FORMAT_RGB_888: return MDP_RGB_888; + case HAL_PIXEL_FORMAT_RGBA_8888: return MDP_RGBA_8888; + case HAL_PIXEL_FORMAT_BGRA_8888: return MDP_BGRA_8888; + case HAL_PIXEL_FORMAT_YCrCb_422_SP: return MDP_Y_CBCR_H2V1; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: return MDP_Y_CRCB_H2V2; } return -1; } @@ -138,27 +140,23 @@ static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) img->height = rhs->h; img->format = get_format(rhs->format); img->offset = hnd->offset; -#if defined(COPYBIT_MSM7K) - if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { - img->offset += hnd->map_offset; - img->memory_id = hnd->gpu_fd; - if (img->format == MDP_RGBA_8888) { - // msm7201A GPU only supports BGRA_8888 destinations - img->format = MDP_BGRA_8888; - } - } else { - img->memory_id = hnd->fd; - } -#else - img->memory_id = hnd->fd; -#endif + #if defined(COPYBIT_MSM7K) + #if defined(USE_ASHMEM) && (TARGET_7x27) + img->memory_id = hnd->fd; + #else //USE_ASHMEM not defined + img->memory_id = hnd->fd; + #endif //end USE_ASHMEM + #else + img->memory_id = hnd->fd; + #endif } /** setup rectangles */ static void set_rects(struct copybit_context_t *dev, struct mdp_blit_req *e, const struct copybit_rect_t *dst, const struct copybit_rect_t *src, - const struct copybit_rect_t *scissor) { + const struct copybit_rect_t *scissor, + uint32_t padding) { struct copybit_rect_t clip; intersect(&clip, scissor, dst); @@ -186,18 +184,30 @@ static void set_rects(struct copybit_context_t *dev, MULDIV(&e->src_rect.x, &e->src_rect.w, src->r - src->l, W); MULDIV(&e->src_rect.y, &e->src_rect.h, src->b - src->t, H); if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) { - e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { + e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - padding; + }else{ + e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + } } + if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) { - e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w); + if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { + e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + }else{ + e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - padding; + } } } /** setup mdp request */ -static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) { +static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req, int flags) { req->alpha = dev->mAlpha; req->transp_mask = MDP_TRANSP_NOP; - req->flags = dev->mFlags | MDP_BLEND_FG_PREMULT; + req->flags = dev->mFlags | flags; +#if defined(COPYBIT_QSD8K) + req->flags |= MDP_BLEND_FG_PREMULT; +#endif } /** copy the bits */ @@ -355,10 +365,10 @@ static int stretch_copybit( if (ctx->mAlpha < 255) { switch (src->format) { // we don't support plane alpha with RGBA formats - case COPYBIT_FORMAT_RGBA_8888: - case COPYBIT_FORMAT_BGRA_8888: - case COPYBIT_FORMAT_RGBA_5551: - case COPYBIT_FORMAT_RGBA_4444: + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: return -EINVAL; } } @@ -383,10 +393,12 @@ static int stretch_copybit( while ((status == 0) && region->next(region, &clip)) { intersect(&clip, &bounds, &clip); mdp_blit_req* req = &list.req[list.count]; - set_infos(ctx, req); + int flags = 0; + + set_infos(ctx, req, flags); set_image(&req->dst, dst); set_image(&req->src, src); - set_rects(ctx, req, dst_rect, src_rect, &clip); + set_rects(ctx, req, dst_rect, src_rect, &clip, src->padding); if (req->src_rect.w<=0 || req->src_rect.h<=0) continue; @@ -462,7 +474,7 @@ static int open_copybit(const struct hw_module_t* module, const char* name, } else { struct fb_fix_screeninfo finfo; if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) { - if (strcmp(finfo.id, "msmfb") == 0) { + if (strncmp(finfo.id, "msmfb", 5) == 0) { /* Success */ status = 0; } else { diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp new file mode 100644 index 0000000..4159dbf --- /dev/null +++ b/libcopybit/copybit_c2d.cpp @@ -0,0 +1,1008 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "copybit_c2d" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "c2d2.h" + +#include +C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id, + C2D_SURFACE_TYPE surface_type, + void *surface_definition, + int32 x, int32 y ); + +C2D_STATUS (*LINK_c2dDraw)( uint32 target_id, + uint32 target_config, C2D_RECT *target_scissor, + uint32 target_mask_id, uint32 target_color_key, + C2D_OBJECT *objects_list, uint32 num_objects ); + +C2D_STATUS (*LINK_c2dFinish)( uint32 target_id); + +C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp); + +C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp ); + +C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id ); + + +/******************************************************************************/ + +#if defined(COPYBIT_Z180) +#define MAX_SCALE_FACTOR (4096) +#define MAX_DIMENSION (4096) +#else +#error "Unsupported HW version" +#endif + +#define G12_DEVICE_NAME "/dev/kgsl-2d0" + +#define COPYBIT_SUCCESS 0 +#define COPYBIT_FAILURE -1 + +#define RGB_SURFACE 0 +#define YUV_SURFACE 1 +#define NUM_SRC_SURFACES 2 +#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) +/******************************************************************************/ + +/** State information for each device instance */ +struct copybit_context_t { + struct copybit_device_t device; + unsigned int src[NUM_SRC_SURFACES]; + unsigned int dst; /* dst surface */ + unsigned int trg_transform; /* target transform */ + C2D_OBJECT blitState; + void *libc2d2; + int g12_device_fd; + int fb_width; + int fb_height; +}; + +struct blitlist{ + uint32_t count; + C2D_OBJECT blitObjects[12]; +}; + +/** + * Common hardware methods + */ + +static int open_copybit(const struct hw_module_t* module, const char* name, + struct hw_device_t** device); + +static struct hw_module_methods_t copybit_module_methods = { + open: open_copybit +}; + +/* + * The COPYBIT Module + */ +struct copybit_module_t HAL_MODULE_INFO_SYM = { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: COPYBIT_HARDWARE_MODULE_ID, + name: "QCT COPYBIT C2D 2.0 Module", + author: "Qualcomm", + methods: ©bit_module_methods + } +}; + + +/* convert COPYBIT_FORMAT to C2D format */ +static int get_format(int format) { + switch (format) { + case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB; + case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB; + case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB; + case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB; + case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA; + case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED; + default: return -EINVAL; + } + return -EINVAL; +} + +/* ------------------------------------------------------------------- *//*! + * \internal + * \brief Get the bpp for a particular color format + * \param color format + * \return bits per pixel +*//* ------------------------------------------------------------------- */ +int c2diGetBpp(int32 colorformat) +{ + + int c2dBpp = 0; + + switch(colorformat&0xFF) + { + case C2D_COLOR_FORMAT_4444_RGBA: + case C2D_COLOR_FORMAT_4444_ARGB: + case C2D_COLOR_FORMAT_1555_ARGB: + case C2D_COLOR_FORMAT_565_RGB: + case C2D_COLOR_FORMAT_5551_RGBA: + c2dBpp = 16; + break; + case C2D_COLOR_FORMAT_8888_RGBA: + case C2D_COLOR_FORMAT_8888_ARGB: + c2dBpp = 32; + break; + case C2D_COLOR_FORMAT_8_L: + case C2D_COLOR_FORMAT_8_A: + c2dBpp = 8; + break; + case C2D_COLOR_FORMAT_4_A: + c2dBpp = 4; + break; + case C2D_COLOR_FORMAT_1: + c2dBpp = 1; + break; + default: + LOGE("%s ERROR", __func__); + break; + } + return c2dBpp; +} + +static uint32 c2d_get_gpuaddr(int device_fd, struct private_handle_t *handle) +{ + if(!handle) + return 0; + + struct kgsl_map_user_mem param; + memset(¶m, 0, sizeof(param)); + param.fd = handle->fd; + param.len = handle->size; + param.offset = handle->offset; + param.hostptr = handle->base; + + if (handle->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) + param.memtype = KGSL_USER_MEM_TYPE_PMEM; + else + param.memtype = KGSL_USER_MEM_TYPE_ASHMEM; + + if (!ioctl(device_fd, IOCTL_KGSL_MAP_USER_MEM, (void *)¶m, sizeof(param))) { + return param.gpuaddr; + } + + return 0; +} + +static uint32 c2d_unmap_gpuaddr(int device_fd, unsigned int gpuaddr) +{ + struct kgsl_sharedmem_free param; + + memset(¶m, 0, sizeof(param)); + param.gpuaddr = gpuaddr; + + ioctl(device_fd, IOCTL_KGSL_SHAREDMEM_FREE, (void *)¶m, sizeof(param)); + return COPYBIT_SUCCESS; +} + +static int is_supported_rgb_format(int format) +{ + switch(format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: { + return COPYBIT_SUCCESS; + } + default: + return COPYBIT_FAILURE; + } +} + +static int is_supported_yuv_format(int format) +{ + switch(format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: { + return COPYBIT_SUCCESS; + } + default: + return COPYBIT_FAILURE; + } +} + +static int calculate_yuv_offset_and_stride(int format, int width, int height, int *offset, int *yStride, int *uvStride) +{ + int aligned_height = 0; + int aligned_width = 0, size = 0; + + switch (format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: { + /* NV12 Tile buffers have their luma height aligned to 32bytes and width + * aligned to 128 bytes. The chroma offset starts at an 8K boundary + */ + aligned_height = ALIGN(height, 32); + aligned_width = ALIGN(width, 128); + size = aligned_width * aligned_height; + *offset = ALIGN(size,8192); + *yStride = aligned_width; + *uvStride = aligned_width; + break; + } + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: { + aligned_width = ALIGN(width, 32); + *offset = aligned_width * height; + *yStride = aligned_width; + *uvStride = aligned_width; + break; + } + default: { + return COPYBIT_FAILURE; + } + } + return COPYBIT_SUCCESS; +} + +/** create C2D surface from copybit image */ +static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32_t *mapped) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + C2D_SURFACE_TYPE surfaceType; + int status = COPYBIT_SUCCESS; + + *cformat = get_format(rhs->format); + if(*cformat == -EINVAL) { + LOGE("%s: invalid format", __func__); + return -EINVAL; + } + + if (handle->gpuaddr == 0) { + handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle); + if(!handle->gpuaddr) { + return COPYBIT_FAILURE; + } + *mapped = 1; + } + + /* create C2D surface */ + if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) { + /* RGB */ + C2D_RGB_SURFACE_DEF surfaceDef; + + surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS); + + surfaceDef.phys = (void*) handle->gpuaddr; + surfaceDef.buffer = (void*) (handle->base); + + surfaceDef.format = *cformat; + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); + + if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { + LOGE("%s: RGB Surface c2dUpdateSurface ERROR", __func__); + goto error; + status = COPYBIT_FAILURE; + } + } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) { + C2D_YUV_SURFACE_DEF surfaceDef; + int offset = 0; + int yStride = 0; + int uvStride = 0; + memset(&surfaceDef, 0, sizeof(surfaceDef)); + surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS); + surfaceDef.format = *cformat; + + status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride); + if(status != COPYBIT_SUCCESS) { + LOGE("calculate_yuv_offset_and_stride error"); + goto error; + } + + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.plane0 = (void*) (handle->base); + surfaceDef.phys0 = (void*) (handle->gpuaddr); + surfaceDef.stride0 = yStride; + + surfaceDef.plane1 = (void*) (handle->base + offset); + surfaceDef.phys1 = (void*) (handle->gpuaddr + offset); + surfaceDef.stride1 = uvStride; + + if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { + LOGE("%s: YUV Surface c2dUpdateSurface ERROR", __func__); + goto error; + status = COPYBIT_FAILURE; + } + } else { + LOGE("%s: invalid format %x", __func__, rhs->format); + goto error; + status = COPYBIT_FAILURE; + } + + return status; + +error: + if(*mapped == 1) { + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + *mapped = 0; + } + return status; +} + +static int set_src_image(int device_fd, uint32 *surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32 *mapped) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + *cformat = get_format(rhs->format); + C2D_SURFACE_TYPE surfaceType; + uint32 gpuaddr = (uint32)handle->gpuaddr; + int status = COPYBIT_SUCCESS; + + if (handle->gpuaddr == 0) + { + handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle); + if(!handle->gpuaddr) + return COPYBIT_FAILURE; + + *mapped = 1; + } + + /* create C2D surface */ + if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) { + /* RGB */ + C2D_RGB_SURFACE_DEF surfaceDef; + surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS); + + surfaceDef.phys = (void*) handle->gpuaddr; + surfaceDef.buffer = (void*) (handle->base); + surfaceDef.buffer = (void*) (handle->base + handle->offset); + + surfaceDef.format = get_format(rhs->format); + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); + + if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) { + LOGE("%s: LINK_c2dCreateSurface error", __func__); + status = COPYBIT_FAILURE; + goto error; + } + } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) { + /* YUV */ + C2D_YUV_SURFACE_DEF surfaceDef; + int offset = 0; + int yStride = 0; + int uvStride = 0; + memset(&surfaceDef, 0, sizeof(surfaceDef)); + + surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS); + surfaceDef.format = get_format(rhs->format); + status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride); + if(status != COPYBIT_SUCCESS) { + LOGE("calculate_yuv_offset_and_stride error"); + goto error; + } + + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.plane0 = (void*) (handle->base); + surfaceDef.phys0 = (void*) handle->gpuaddr; + surfaceDef.stride0 = yStride; + + surfaceDef.plane1 = (void*) (handle->base + offset); + surfaceDef.phys1 = (void*) (handle->gpuaddr + offset); + surfaceDef.stride1 = uvStride; + + if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType, (void*)&surfaceDef)) { + LOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__); + status = COPYBIT_FAILURE; + goto error; + } + } else { + LOGE("%s: Invalid format %x", __func__, rhs->format); + status = COPYBIT_FAILURE; + } + + return COPYBIT_SUCCESS; + +error: + if(*mapped == 1) { + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + *mapped = 0; + } + return status; +} + +void unset_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, uint32 mmapped) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + + if (mmapped && handle->gpuaddr) { + // Unmap this gpuaddr + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + } +} + +static int blit_to_target(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + uint32 cformat = get_format(rhs->format); + C2D_SURFACE_TYPE surfaceType; + uint32 memoryMapped = 0; + int status = COPYBIT_SUCCESS; + + if (!handle->gpuaddr) { + handle->gpuaddr = c2d_get_gpuaddr(device_fd,handle); + if(!handle->gpuaddr) + return COPYBIT_FAILURE; + + memoryMapped = 1; + } + + /* create C2D surface */ + + if(cformat) { + /* RGB */ + C2D_RGB_SURFACE_DEF surfaceDef; + memset(&surfaceDef, 0, sizeof(surfaceDef)); + + surfaceDef.buffer = (void*) handle->base; + surfaceDef.phys = (void*) handle->gpuaddr; + + surfaceType = C2D_SURFACE_RGB_HOST; + surfaceDef.format = get_format(rhs->format); + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); + + if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) { + LOGE("%s: LINK_c2dReadSurface ERROR", __func__); + status = COPYBIT_FAILURE; + goto done; + } + } + else { + /* YUV */ + /* TODO */ + } + +done: + if (memoryMapped) { + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + } + return status; +} + +/** setup rectangles */ +static void set_rects(struct copybit_context_t *ctx, + C2D_OBJECT *c2dObject, + const struct copybit_rect_t *dst, + const struct copybit_rect_t *src, + const struct copybit_rect_t *scissor) +{ + + if((ctx->trg_transform & C2D_TARGET_ROTATE_90) && + (ctx->trg_transform & C2D_TARGET_ROTATE_180)) { + /* target rotation is 270 */ + c2dObject->target_rect.x = (dst->t)<<16; + c2dObject->target_rect.y = (ctx->fb_width - (dst->r))<<16; + c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16; + c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16; + } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) { + c2dObject->target_rect.x = (ctx->fb_height - dst->b)<<16; + c2dObject->target_rect.y = (dst->l)<<16; + c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16; + c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16; + } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) { + c2dObject->target_rect.y = (ctx->fb_height - dst->b)<<16; + c2dObject->target_rect.x = (ctx->fb_width - dst->r)<<16; + c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16; + c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16; + } else { + c2dObject->target_rect.x = (dst->l)<<16; + c2dObject->target_rect.y = (dst->t)<<16; + c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16; + c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16; + } + c2dObject->config_mask |= C2D_TARGET_RECT_BIT; + + c2dObject->source_rect.x = (src->l)<<16; + c2dObject->source_rect.y = (src->t)<<16; + c2dObject->source_rect.height = ((src->b) - (src->t))<<16; + c2dObject->source_rect.width = ((src->r) - (src->l))<<16; + c2dObject->config_mask |= C2D_SOURCE_RECT_BIT; + + c2dObject->scissor_rect.x = scissor->l; + c2dObject->scissor_rect.y = scissor->t; + c2dObject->scissor_rect.height = (scissor->b) - (scissor->t); + c2dObject->scissor_rect.width = (scissor->r) - (scissor->l); + + c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT; +} + +/** copy the bits */ +static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target) +{ + int objects; + + for(objects = 0; objects < list->count; objects++) { + list->blitObjects[objects].next = &(list->blitObjects[objects+1]); + } + + if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects, + list->count)) { + LOGE("%s: LINK_c2dDraw ERROR"); + return COPYBIT_FAILURE; + } + + return COPYBIT_SUCCESS; +} + +/*****************************************************************************/ + +/** Set a parameter to value */ +static int set_parameter_copybit( + struct copybit_device_t *dev, + int name, + int value) +{ + struct copybit_context_t* ctx = (struct copybit_context_t*)dev; + if (!ctx) { + LOGE("%s: null context", __func__); + return -EINVAL; + } + + switch(name) { + case COPYBIT_ROTATION_DEG: + ctx->blitState.rotation = value<<16; + /* SRC rotation */ + if(!value) + ctx->blitState.config_mask &=~C2D_ROTATE_BIT;; + break; + case COPYBIT_PLANE_ALPHA: + if (value < 0) value = 0; + if (value >= 256) value = 255; + + ctx->blitState.global_alpha = value; + + if(ctx->blitState.global_alpha<255) + ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT; + else + ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT; + break; + case COPYBIT_DITHER: + /* TODO */ + break; + case COPYBIT_BLUR: + /* TODO */ + break; + case COPYBIT_TRANSFORM: + ctx->blitState.config_mask &=~C2D_ROTATE_BIT; + ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT; + ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT; + ctx->trg_transform = C2D_TARGET_ROTATE_0; + + if((value&0x7) == COPYBIT_TRANSFORM_ROT_180) + ctx->trg_transform = C2D_TARGET_ROTATE_180; + else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270) + ctx->trg_transform = C2D_TARGET_ROTATE_90; + else { + if(value©BIT_TRANSFORM_FLIP_H) + ctx->blitState.config_mask |= C2D_MIRROR_H_BIT; + if(value©BIT_TRANSFORM_FLIP_V) + ctx->blitState.config_mask |= C2D_MIRROR_V_BIT; + if(value©BIT_TRANSFORM_ROT_90) + ctx->trg_transform = C2D_TARGET_ROTATE_270; + } + break; + default: + LOGE("%s: default case", __func__); + return -EINVAL; + break; + } + + return COPYBIT_SUCCESS; +} + +/** Get a static info value */ +static int get(struct copybit_device_t *dev, int name) +{ + struct copybit_context_t* ctx = (struct copybit_context_t*)dev; + int value; + + if (!ctx) { + LOGE("%s: null context error", __func__); + return -EINVAL; + } + + switch(name) { + case COPYBIT_MINIFICATION_LIMIT: + value = MAX_SCALE_FACTOR; + break; + case COPYBIT_MAGNIFICATION_LIMIT: + value = MAX_SCALE_FACTOR; + break; + case COPYBIT_SCALING_FRAC_BITS: + value = 32; + break; + case COPYBIT_ROTATION_STEP_DEG: + value = 1; + break; + default: + LOGE("%s: default case", __func__); + value = -EINVAL; + } + return value; +} + +static int is_alpha(int cformat) +{ + int alpha = 0; + switch (cformat & 0xFF) { + case C2D_COLOR_FORMAT_8888_ARGB: + case C2D_COLOR_FORMAT_8888_RGBA: + case C2D_COLOR_FORMAT_5551_RGBA: + case C2D_COLOR_FORMAT_4444_ARGB: + alpha = 1; + break; + default: + alpha = 0; + break; + } + + if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA)) + alpha = 0; + + return alpha; +} + +/** do a stretch blit type operation */ +static int stretch_copybit( + struct copybit_device_t *dev, + struct copybit_image_t const *dst, + struct copybit_image_t const *src, + struct copybit_rect_t const *dst_rect, + struct copybit_rect_t const *src_rect, + struct copybit_region_t const *region) +{ + struct copybit_context_t* ctx = (struct copybit_context_t*)dev; + int status = COPYBIT_SUCCESS; + uint32 maxCount; + uint32 src_mapped = 0, trg_mapped = 0; + blitlist list; + C2D_OBJECT *req; + memset(&list, 0, sizeof(list)); + int cformat; + c2d_ts_handle timestamp; + uint32 surface_index = 0; + + if (!ctx) { + LOGE("%s: null context error", __func__); + return -EINVAL; + } + + if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) { + LOGE("%s: src dimension error", __func__); + return -EINVAL; + } + + if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) { + LOGE("%s : dst dimension error dst w %d h %d", __func__, dst->w, dst->h); + return -EINVAL; + } + + maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT); + + struct copybit_rect_t clip; + list.count = 0; + + status = set_image(ctx->g12_device_fd, ctx->dst, dst, &cformat, &trg_mapped); + if(status) { + LOGE("%s: set_image error", __func__); + return COPYBIT_FAILURE; + } + + if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) { + surface_index = RGB_SURFACE; + } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) { + surface_index = YUV_SURFACE; + } else { + LOGE("%s: Invalid source surface format %x", __func__, src->format); + return -EINVAL; + } + + status = set_image(ctx->g12_device_fd, ctx->src[surface_index], src, &cformat, &src_mapped); + if(status) { + LOGE("%s: set_src_image error", __func__); + return COPYBIT_FAILURE; + } + + if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) { + ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; + if(!(ctx->blitState.global_alpha)) { + // src alpha is zero + unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); + unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); + return status; + } + } else { + if(is_alpha(cformat)) + ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; + else + ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; + } + + ctx->blitState.surface_id = ctx->src[surface_index]; + + while ((status == 0) && region->next(region, &clip)) { + req = &(list.blitObjects[list.count]); + memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT)); + + set_rects(ctx, req, dst_rect, src_rect, &clip); + + if (++list.count == maxCount) { + status = msm_copybit(ctx, &list, ctx->dst); + list.count = 0; + } + } + if ((status == 0) && list.count) { + status = msm_copybit(ctx, &list, ctx->dst); + } + + if(LINK_c2dFinish(ctx->dst)) { + LOGE("%s: LINK_c2dFinish ERROR", __func__); + } + + + unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); + unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); + + return status; +} + +/** Perform a blit type operation */ +static int blit_copybit( + struct copybit_device_t *dev, + struct copybit_image_t const *dst, + struct copybit_image_t const *src, + struct copybit_region_t const *region) +{ + struct copybit_rect_t dr = { 0, 0, dst->w, dst->h }; + struct copybit_rect_t sr = { 0, 0, src->w, src->h }; + return stretch_copybit(dev, dst, src, &dr, &sr, region); +} + +/*****************************************************************************/ + +/** Close the copybit device */ +static int close_copybit(struct hw_device_t *dev) +{ + struct copybit_context_t* ctx = (struct copybit_context_t*)dev; + if (ctx) { + LINK_c2dDestroySurface(ctx->dst); + for(int i = 0; i src[i]); + } + + if (ctx->libc2d2) { + ::dlclose(ctx->libc2d2); + LOGV("dlclose(libc2d2)"); + } + + if(ctx->g12_device_fd) + close(ctx->g12_device_fd); + free(ctx); + } + + return 0; +} + +/** Open a new instance of a copybit device using name */ +static int open_copybit(const struct hw_module_t* module, const char* name, + struct hw_device_t** device) +{ + int status = COPYBIT_SUCCESS; + C2D_RGB_SURFACE_DEF surfDefinition = {0}; + C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ; + struct copybit_context_t *ctx; + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i=0; + char fbName[64]; + + ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t)); + if(!ctx) { + LOGE("%s: malloc failed", __func__); + return COPYBIT_FAILURE; + } + + /* initialize drawstate */ + memset(ctx, 0, sizeof(*ctx)); + + ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW); + if (!ctx->libc2d2) { + LOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror()); + status = COPYBIT_FAILURE; + goto error; + } + *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2, + "c2dCreateSurface"); + *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2, + "c2dUpdateSurface"); + *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2, + "c2dReadSurface"); + *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw"); + *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush"); + *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish"); + *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2, + "c2dWaitTimestamp"); + *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2, + "c2dDestroySurface"); + + if(!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface + || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish + || !LINK_c2dDestroySurface) { + LOGE("%s: dlsym ERROR", __func__); + status = COPYBIT_FAILURE; + goto error1; + } + + ctx->device.common.tag = HARDWARE_DEVICE_TAG; + ctx->device.common.version = 1; + ctx->device.common.module = (hw_module_t*)(module); + ctx->device.common.close = close_copybit; + ctx->device.set_parameter = set_parameter_copybit; + ctx->device.get = get; + ctx->device.blit = blit_copybit; + ctx->device.stretch = stretch_copybit; + ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT; + ctx->trg_transform = C2D_TARGET_ROTATE_0; + ctx->g12_device_fd = open(G12_DEVICE_NAME, O_RDWR | O_SYNC); + if(ctx->g12_device_fd < 0) { + LOGE("%s: g12_device_fd open failed", __func__); + status = COPYBIT_FAILURE; + goto error1; + } + + /* Create RGB Surface */ + surfDefinition.buffer = (void*)0xdddddddd; + surfDefinition.phys = (void*)0xdddddddd; + surfDefinition.stride = 1 * 4; + surfDefinition.width = 1; + surfDefinition.height = 1; + surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB; + + if(LINK_c2dCreateSurface(&ctx->dst,C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | + C2D_SURFACE_WITH_PHYS), &surfDefinition)) { + LOGE("%s: create ctx->dst failed", __func__); + status = COPYBIT_FAILURE; + goto error2; + } + + if(LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | + C2D_SURFACE_WITH_PHYS), &surfDefinition)) { + LOGE("%s: create ctx->src[RGB_SURFACE] failed", __func__); + status = COPYBIT_FAILURE; + goto error3; + } + + /* Create YUV source surface */ + yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12; + + yuvSurfaceDef.width = 4; + yuvSurfaceDef.height = 4; + yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa; + yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa; + yuvSurfaceDef.stride0 = 4; + + yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa; + yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa; + yuvSurfaceDef.stride1 = 4; + + if(LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE]),C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), + &yuvSurfaceDef)) { + LOGE("%s: create ctx->src[YUV_SURFACE] failed", __func__); + status = COPYBIT_FAILURE; + goto error4; + } + + if (status == COPYBIT_SUCCESS) + *device = &ctx->device.common; + else { + close_copybit(&ctx->device.common); + goto error4; + } + + while ((fd==-1) && device_template[i]) { + snprintf(fbName, 64, device_template[i], 0); + fd = open(fbName, O_RDWR, 0); + i++; + } + if (fd < 0) + goto error4; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + goto error5; + + ctx->fb_width = info.xres; + ctx->fb_height = info.yres; + close(fd); + return status; + +error5: + close(fd); + fd = -1; +error4: + LINK_c2dDestroySurface(ctx->src[RGB_SURFACE]); +error3: + LINK_c2dDestroySurface(ctx->dst); +error2: + close(ctx->g12_device_fd); +error1: + ::dlclose(ctx->libc2d2); +error: + free(ctx); + + return status; +}