diff --git a/Android.bp b/Android.bp index 220c656..6065417 100644 --- a/Android.bp +++ b/Android.bp @@ -108,10 +108,17 @@ cc_defaults { "libnativebase_headers", ], + include_dirs: [ + "frameworks/native/libs/nativewindow/include-private/private", + ], + shared_libs: [ "libcutils", "libnativewindow", "libhardware", + "libui", + "libutils", + "libutilscallstack", ], static_libs: [ @@ -139,6 +146,8 @@ cc_defaults { "-Wcast-qual", "-Wcast-align", "-Wno-unused-parameter", + "-DLOG_TAG=\"hybris\"", + "-DEGL_EGLEXT_PROTOTYPES", ], vendor: true, @@ -149,3 +158,25 @@ cc_defaults { "libdl", ], } + +cc_library_shared { + name: "gralloc.gbm_proxy", + srcs: [ + "gralloc_gbm_proxy/gralloc_gbm.cpp", + "gralloc_gbm_proxy/gralloc.cpp", + "gralloc_gbm_proxy/gbm.cpp", + "gralloc_gbm_proxy/gbm_proxy.cpp", + ], + + vendor: true, + + shared_libs: [ + "libdrm", + "liblog", + "libcutils", + "libhardware", + ], + export_include_dirs: ["."], + relative_install_path: "hw", + proprietary: true, +} \ No newline at end of file diff --git a/egl/blit-framebuffer.cpp b/egl/blit-framebuffer.cpp index 930972b..01aab88 100644 --- a/egl/blit-framebuffer.cpp +++ b/egl/blit-framebuffer.cpp @@ -12,6 +12,7 @@ #include "egl-display.h" #include "pixel-format.h" +#include #define HYBRIS_GET_SYMBOL_ADDRESS(symbol) \ ({ egl::EglProxy::Instance()->Api().eglGetProcAddress(#symbol); }) @@ -48,96 +49,95 @@ HYBRIS_IMPLEMENT_FUNCTION0(GLenum, glGetError); HYBRIS_IMPLEMENT_FUNCTION0(void, glFinish); HYBRIS_IMPLEMENT_FUNCTION4(void, glViewport, GLint, GLint, GLsizei, GLsizei); + +HYBRIS_IMPLEMENT_FUNCTION10(void, glBlitFramebuffer, GLint, GLint, GLint, GLint, + GLint, GLint, GLint, GLint, GLbitfield, GLenum); } namespace { -class FrameBufferBinder { - public: - GLint GetFbo() const { return fbo_; } - - explicit FrameBufferBinder(GLenum fb_target, EGLImage image) - : fb_target_(fb_target) { - GLenum fb_bound = (fb_target_ == GL_READ_FRAMEBUFFER) - ? GL_READ_FRAMEBUFFER_BINDING - : GL_DRAW_FRAMEBUFFER_BINDING; - glGetIntegerv(fb_bound, &prev_fbo_); - if (prev_fbo_ != 0) { - glBindFramebuffer(fb_target_, 0); - } - - GLint curr_tex_bind = {}; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &curr_tex_bind); - - glGenTextures(1, &tex_); - glBindTexture(GL_TEXTURE_2D, tex_); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); - - glBindTexture(GL_TEXTURE_2D, curr_tex_bind); - - glGenFramebuffers(1, &fbo_); - glBindFramebuffer(fb_target_, fbo_); - glFramebufferTexture2D(fb_target_, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - tex_, 0); - if (auto status = glCheckFramebufferStatus(fb_target_); - status != GL_FRAMEBUFFER_COMPLETE) { - ALOGE("glFramebufferTexture2D: FBO not complete: 0x%04X", status); - } - } - - ~FrameBufferBinder() { - if (fbo_ != 0) { - glBindFramebuffer(fb_target_, 0); - glDeleteFramebuffers(1, &fbo_); - } - if (tex_ != 0) { - glDeleteTextures(1, &tex_); +const char* eglStrError(EGLint err) +{ + switch (err){ + case EGL_SUCCESS: return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; + case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; + case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; + case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; + case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; + case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; + case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; + case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; + case 0x502: return "GL_INVALID_OPERATION"; + default: return "UNKNOWN"; } - if (prev_fbo_ != 0) { - glBindFramebuffer(fb_target_, prev_fbo_); - } - } - - private: - GLenum fb_target_{}; - GLint prev_fbo_{}; - GLuint tex_{}; - GLuint fbo_{}; -}; - -class Texture2DBinder { - public: - Texture2DBinder(GLuint tex) { - glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev_tex_); - glBindTexture(GL_TEXTURE_2D, tex); - } - ~Texture2DBinder() { glBindTexture(GL_TEXTURE_2D, prev_tex_); } - - private: - GLint prev_tex_{}; -}; - -void CopyFromFramebuffer(EGLImage egl_image, int32_t width, int32_t height, +} +void CopyFromFramebuffer(EGLImage egl_image, int32_t width, int32_t height, int32_t flip, GLint fbo = 0) { GLuint tmp_tex = {}; GLint curr_tex_bind = {}; - GLint prev_read_fbo = {}; + GLint prev_read_fbo = {}, prev_draw_fbo = {}; glGetIntegerv(GL_TEXTURE_BINDING_2D, &curr_tex_bind); glGenTextures(1, &tmp_tex); glBindTexture(GL_TEXTURE_2D, tmp_tex); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image); + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + ALOGE("glEGLImageTargetTexture2DOES fail %dx%d err:%s(0x%x)", + width, height, eglStrError(err), err); + } - // gles3 + // 保存当前帧缓冲状态 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prev_read_fbo); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_draw_fbo); + if (prev_read_fbo != fbo) { + // 绑定源帧缓冲(读缓冲) glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); } - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height); + // 创建临时帧缓冲,将纹理作为颜色附件 + GLuint temp_fbo; + glGenFramebuffers(1, &temp_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, temp_fbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, tmp_tex, 0); + err = glGetError(); + if (err != GL_NO_ERROR) { + ALOGE("glFramebufferTexture2D fail %dx%d err:%s(0x%x)", + width, height, eglStrError(err), err); + } + + // glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height); + if (flip) { + // 垂直翻转拷贝:源矩形 (0,0,width,height),目标矩形 (0,height,width,0) + glBlitFramebuffer(0, 0, width, height, + 0, height, width, 0, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + } else { + glBlitFramebuffer(0, 0, width, height, + 0, 0, width, height, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + } + err = glGetError(); + if (err != GL_NO_ERROR) { + ALOGE("glBlitFramebuffer fail %dx%d err:%s(0x%x)", + width, height, eglStrError(err), err); + } + glFinish(); if (prev_read_fbo != fbo) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, (GLuint)prev_read_fbo); + // 恢复状态 + glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo); } + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo); + glDeleteFramebuffers(1, &temp_fbo); glBindTexture(GL_TEXTURE_2D, curr_tex_bind); glDeleteTextures(1, &tmp_tex); @@ -218,60 +218,6 @@ bool GetTextureFormatParameters(GLint internal_format, GLenum *tex_format, namespace egl { -EGLImage Texture2D::EglImage() { - if (!egl_img_) { - auto &api = egl::EglProxy::Instance()->Api(); - auto dpy = api.eglGetCurrentDisplay(); - auto context = api.eglGetCurrentContext(); - auto tex = Id(); - if (auto egl_img = - api.eglCreateImage(dpy, context, EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer)(uintptr_t)tex, nullptr); - egl_img) { - auto destroy = api.eglDestroyImage; - egl_img_.reset(egl_img, - [destroy, dpy](EGLImage img) { destroy(dpy, img); }); - } - } - return egl_img_.get(); -} - -GLuint Texture2D::Id() { return tex_; } - -void Texture2D::Delete() { - egl_img_.reset(); - if (tex_ != 0) { - glDeleteTextures(1, &tex_); - tex_ = 0; - } -} - -Texture2DPtr Texture2D::CreateTexture(GLenum internal_format, int32_t width, - int32_t height) { - GLenum tex_format; - GLenum pixel_type; - GLint sized_internal_format; - if (!GetTextureFormatParameters(internal_format, &tex_format, &pixel_type, - &sized_internal_format)) { - ALOGE("Not support texture internal format 0x%04X", internal_format); - return nullptr; - } - - GLuint tex = {}; - glGenTextures(1, &tex); - Texture2DBinder tex2d(tex); - - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, tex_format, - pixel_type, nullptr); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - return std::make_shared(tex); -} - void BlitFramebuffer::Blit(ANativeWindowBuffer *native_buffer) { if (!native_buffer) { return; @@ -286,7 +232,9 @@ void BlitFramebuffer::Blit(ANativeWindowBuffer *native_buffer) { auto image = std::make_shared(dpy_, proxy_, native_buffer); if (auto egl_img = image->CreateImage(); egl_img != EGL_NO_IMAGE) { - CopyFromFramebuffer(egl_img, width, height); + int flip = (native_buffer->usage & GRALLOC_USAGE_PRIVATE_1); + CopyFromFramebuffer(egl_img, width, height, flip); + image->DestroyImage(); } diff --git a/egl/blit-framebuffer.h b/egl/blit-framebuffer.h index b6a2a20..4565c7e 100644 --- a/egl/blit-framebuffer.h +++ b/egl/blit-framebuffer.h @@ -11,9 +11,6 @@ namespace egl { class Display; -class Texture2D; -using Texture2DPtr = std::shared_ptr; - class BlitFramebuffer { public: explicit BlitFramebuffer(EglProxyPtr proxy, Display *dpy) @@ -28,26 +25,4 @@ class BlitFramebuffer { using BlitFramebufferPtr = std::shared_ptr; -class Texture2D { - public: - Texture2D() = default; - Texture2D(GLuint tex) : tex_(tex){}; - ~Texture2D() { Delete(); } - - EGLImage EglImage(); - GLuint Id(); - - void Delete(); - - Texture2D(const Texture2D &) = delete; - Texture2D &operator=(const Texture2D &) = delete; - - static Texture2DPtr CreateTexture(GLenum internal_format, int32_t width, - int32_t height); - - private: - std::shared_ptr egl_img_{}; - GLuint tex_{}; -}; - } // namespace egl \ No newline at end of file diff --git a/egl/egl-display.cpp b/egl/egl-display.cpp index 856bbd1..0b9e47d 100644 --- a/egl/egl-display.cpp +++ b/egl/egl-display.cpp @@ -474,18 +474,29 @@ EGLBoolean AndroidDisplay::ChooseConfig(const EGLint *attrib_list, auto attribs = egl::misc::DupAttributes(attrib_list); EGLint native_visual_id = -1; + EGLint red_size=0, green_size=0, blue_size=0, alpha_size=0; bool has_surface_type = false; + bool has_alpha_type = false; for (auto it = attribs.begin(); *it != EGL_NONE; it += 2) { if (*it == EGL_SURFACE_TYPE) { auto &type = *std::next(it); + has_surface_type = true; if ((type & EGL_WINDOW_BIT) != 0) { type &= ~EGL_WINDOW_BIT; type &= ~EGL_SWAP_BEHAVIOR_PRESERVED_BIT; type |= EGL_PBUFFER_BIT; - has_surface_type = true; } } else if (*it == EGL_NATIVE_VISUAL_ID) { native_visual_id = *std::next(it); + } else if (*it == EGL_RED_SIZE) { + red_size = *std::next(it); + } else if (*it == EGL_GREEN_SIZE) { + green_size = *std::next(it); + } else if (*it == EGL_BLUE_SIZE) { + blue_size = *std::next(it); + } else if (*it == EGL_ALPHA_SIZE) { + alpha_size = *std::next(it); + has_alpha_type = true; } } @@ -532,6 +543,20 @@ EGLBoolean AndroidDisplay::ChooseConfig(const EGLint *attrib_list, misc::ApendAttributes(surface_config, attribs); } + if (!has_alpha_type && red_size > 0 && green_size > 0 && blue_size > 0) { + if (green_size == 10) { + alpha_size = 2; + } else if (green_size == 8) { + alpha_size = 8; + } + const EGLint alpha_config[] = { + EGL_ALPHA_SIZE, + alpha_size, + EGL_NONE, + }; + misc::ApendAttributes(alpha_config, attribs); + } + auto ret = api.eglChooseConfig(dpy, attribs.data(), configs, config_size, num_config); if (!ret) { @@ -539,6 +564,7 @@ EGLBoolean AndroidDisplay::ChooseConfig(const EGLint *attrib_list, proxy_->StrLastError().c_str(), misc::StringifyAttributes(attrib_list).c_str()); } + return ret; } @@ -550,6 +576,7 @@ EGLBoolean AndroidDisplay::GetConfigAttrib(EGLConfig config, EGLint attribute, HalPixelFormat pixel_format; if (!GetFormatSizeFromConfig(config, pixel_format)) { // EGL_BAD_ATTRIBUTE + ALOGD("eglGetConfigAttrib failed from attribute : 0x%04X", attribute); return EGL_FALSE; } *value = pixel_format.PixelFormat(); diff --git a/egl/egl-image.cpp b/egl/egl-image.cpp index e52b66e..0fb4822 100644 --- a/egl/egl-image.cpp +++ b/egl/egl-image.cpp @@ -165,13 +165,13 @@ EGLBoolean AndroidBufferImage::FillAttribs( if (buffer_basic_info.num_planes > 1) { // must be planar or semi-planar YUV format attribs[atti++] = EGL_SAMPLE_RANGE_HINT_EXT; - attribs[atti++] = buffer_color_info.sample_range; + attribs[atti++] = buffer_color_info.sample_range > 0 ? buffer_color_info.sample_range : __DRI_YUV_NARROW_RANGE; attribs[atti++] = EGL_YUV_COLOR_SPACE_HINT_EXT; - attribs[atti++] = buffer_color_info.yuv_color_space; + attribs[atti++] = buffer_color_info.yuv_color_space > 0 ? buffer_color_info.yuv_color_space : __DRI_YUV_COLOR_SPACE_ITU_REC601; attribs[atti++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT; - attribs[atti++] = buffer_color_info.horizontal_siting; + attribs[atti++] = buffer_color_info.horizontal_siting > 0 ? buffer_color_info.horizontal_siting : __DRI_YUV_CHROMA_SITING_0; attribs[atti++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT; - attribs[atti++] = buffer_color_info.vertical_siting; + attribs[atti++] = buffer_color_info.vertical_siting > 0 ? buffer_color_info.vertical_siting : __DRI_YUV_CHROMA_SITING_0; } auto has_dmabuf_modifier = diff --git a/egl/egl-proxy.cpp b/egl/egl-proxy.cpp index 86684e0..6b20a57 100644 --- a/egl/egl-proxy.cpp +++ b/egl/egl-proxy.cpp @@ -257,7 +257,7 @@ bool EglProxy::Initialize() { GetEglVersion(version, egl_major, egl_minor); } - if (egl_major != kEglMajorVersion || egl_minor < kEglMinorMinVersion) { + if (egl_major != kEglMajorVersion || egl_minor <= kEglMinorMinVersion) { ALOGE("EGL API version (%d.%d) is too low", egl_major, egl_minor); return false; } @@ -410,6 +410,8 @@ void EglProxy::InitializeApiExtensions() { } while (0) GETSYMBOLADDR(eglSwapBuffersWithDamageKHR); + GETSYMBOLADDR(eglQueryDmaBufFormatsEXT); + GETSYMBOLADDR(eglQueryDmaBufModifiersEXT); #undef GETSYMBOLADDR } diff --git a/egl/egl-proxy.h b/egl/egl-proxy.h index 22ea72e..ca3f7dc 100644 --- a/egl/egl-proxy.h +++ b/egl/egl-proxy.h @@ -72,6 +72,8 @@ struct Egl15 : public Egl14 { struct EglExteions { PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC eglSwapBuffersWithDamageKHR = {}; + PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = {}; + PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = {}; }; struct EglApi : public Egl15, public EglExteions {}; diff --git a/egl/egl.cpp b/egl/egl.cpp index 8aedb6a..8c4eae7 100644 --- a/egl/egl.cpp +++ b/egl/egl.cpp @@ -171,6 +171,11 @@ HYBRIS_IMPLEMENT_FUNCTION4(EGLSurface, eglCreatePlatformPixmapSurface, HYBRIS_IMPLEMENT_FUNCTION3(EGLBoolean, eglWaitSync, EGLDisplay, EGLSync, EGLint); + +extern EGLBoolean eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats); +extern EGLBoolean eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers, + EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers); + } namespace { @@ -346,6 +351,12 @@ eglGetProcAddress(const char *procname) { } else if (strcmp(procname, "eglSwapBuffersWithDamageKHR") == 0) { return reinterpret_cast<__eglMustCastToProperFunctionPointerType>( eglSwapBuffersWithDamageKHR); + } else if (strcmp(procname, "eglQueryDmaBufFormatsEXT") == 0) { + return reinterpret_cast<__eglMustCastToProperFunctionPointerType>( + eglQueryDmaBufFormatsEXT); + } else if (strcmp(procname, "eglQueryDmaBufModifiersEXT") == 0) { + return reinterpret_cast<__eglMustCastToProperFunctionPointerType>( + eglQueryDmaBufModifiersEXT); } if (auto addr = api.eglGetProcAddress(procname); addr) { @@ -385,6 +396,23 @@ HYBRIS_VISIBILITY const char *eglQueryString(EGLDisplay dpy, EGLint name) { return egl::EglProxy::Instance()->Api().eglQueryString(dpy, name); } +HYBRIS_VISIBILITY EGLBoolean eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats) { + EGLBoolean ret = EGL_FALSE; + if (egl::EglProxy::Instance()->Api().eglQueryDmaBufFormatsEXT) { + ret = egl::EglProxy::Instance()->Api().eglQueryDmaBufFormatsEXT(dpy, max_formats, formats, num_formats); + } + return ret; +} + +HYBRIS_VISIBILITY EGLBoolean eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers, + EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers) { + EGLBoolean ret = EGL_FALSE; + if (egl::EglProxy::Instance()->Api().eglQueryDmaBufModifiersEXT) { + ret = egl::EglProxy::Instance()->Api().eglQueryDmaBufModifiersEXT(dpy, format, max_modifiers, modifiers, external_only, num_modifiers); + } + return ret; +} + HYBRIS_VISIBILITY EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) { auto const &api = egl::EglProxy::Instance()->Api(); diff --git a/egl/pixel-format.cpp b/egl/pixel-format.cpp index af562f9..c517155 100644 --- a/egl/pixel-format.cpp +++ b/egl/pixel-format.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace { @@ -81,6 +82,12 @@ bool HalPixelFormat::BuildFormat(int32_t red_size, int32_t green_size, } else if ((red_size == 10) && (green_size == 10) && (blue_size == 10) && (alpha_size == 2)) { format = HAL_PIXEL_FORMAT_RGBA_1010102; + } else if ((red_size == 10) && (green_size == 10) && (blue_size == 10) && + (alpha_size == 0)) { + format = HAL_PIXEL_FORMAT_RGBX_8888; + red_size = 8; + green_size = 8; + blue_size = 8; // } else if ((red_size == 5) && (green_size == 5) && (blue_size == 5) && // (alpha_size == 1)) { // format = HAL_PIXEL_FORMAT_RGBA_5551; @@ -88,6 +95,8 @@ bool HalPixelFormat::BuildFormat(int32_t red_size, int32_t green_size, // (alpha_size == 4)) { // format = HAL_PIXEL_FORMAT_RGBA_4444; } else { + ALOGD("BuildFormat failed: R:%d, G:%d, B:%d, A:%d", + red_size, green_size, blue_size, alpha_size); return false; } diff --git a/gralloc_gbm_proxy/gbm.cpp b/gralloc_gbm_proxy/gbm.cpp new file mode 100755 index 0000000..00ad458 --- /dev/null +++ b/gralloc_gbm_proxy/gbm.cpp @@ -0,0 +1,259 @@ +#include "gbm.h" +#include "gbm_proxy.h" + +int +gbm_device_get_fd(struct gbm_device *gbm) +{ + return GbmProxy::Instance()->Api().gbm_device_get_fd(gbm); +} + +const char * +gbm_device_get_backend_name(struct gbm_device *gbm) +{ + return GbmProxy::Instance()->Api().gbm_device_get_backend_name(gbm); +} + +int +gbm_device_is_format_supported(struct gbm_device *gbm, + uint32_t format, uint32_t flags) +{ + return GbmProxy::Instance()->Api().gbm_device_is_format_supported(gbm, format, flags); +} + +int +gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm, + uint32_t format, + uint64_t modifier) +{ + return GbmProxy::Instance()->Api().gbm_device_get_format_modifier_plane_count(gbm, format, modifier); +} + +void +gbm_device_destroy(struct gbm_device *gbm) +{ + GbmProxy::Instance()->Api().gbm_device_destroy(gbm); +} + +struct gbm_device * +gbm_create_device(int fd) +{ + return GbmProxy::Instance()->Api().gbm_create_device(fd); +} + +struct gbm_bo * +gbm_bo_create(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags) +{ + return GbmProxy::Instance()->Api().gbm_bo_create(gbm, width, height, format, flags); +} + +struct gbm_bo * +gbm_bo_create_with_modifiers(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count) +{ + return GbmProxy::Instance()->Api().gbm_bo_create_with_modifiers(gbm, width, height, format, modifiers, count); +} + +struct gbm_bo * +gbm_bo_create_with_modifiers2(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count, + uint32_t flags) +{ + return GbmProxy::Instance()->Api().gbm_bo_create_with_modifiers2(gbm, width, height, format, modifiers, count, flags); +} + +struct gbm_bo * +gbm_bo_import(struct gbm_device *gbm, uint32_t type, + void *buffer, uint32_t flags) +{ + return GbmProxy::Instance()->Api().gbm_bo_import(gbm, type, buffer, flags); +} + +void * +gbm_bo_map(struct gbm_bo *bo, + uint32_t x, uint32_t y, uint32_t width, uint32_t height, + uint32_t flags, uint32_t *stride, void **map_data) +{ + return GbmProxy::Instance()->Api().gbm_bo_map(bo, x, y, width, height, flags, stride, map_data); +} + +void +gbm_bo_unmap(struct gbm_bo *bo, void *map_data) +{ + GbmProxy::Instance()->Api().gbm_bo_unmap(bo, map_data); +} + +uint32_t +gbm_bo_get_width(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_width(bo); +} + +uint32_t +gbm_bo_get_height(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_height(bo); +} + +uint32_t +gbm_bo_get_stride(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_stride(bo); +} + +uint32_t +gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_stride_for_plane(bo, plane); +} + +uint32_t +gbm_bo_get_format(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_format(bo); +} + +uint32_t +gbm_bo_get_bpp(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_bpp(bo); +} + +uint32_t +gbm_bo_get_offset(struct gbm_bo *bo, int plane) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_offset(bo, plane); +} + +struct gbm_device * +gbm_bo_get_device(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_device(bo); +} + +union gbm_bo_handle +gbm_bo_get_handle(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_handle(bo); +} + +int +gbm_bo_get_fd(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_fd(bo); +} + +uint64_t +gbm_bo_get_modifier(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_modifier(bo); +} + +int +gbm_bo_get_plane_count(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_plane_count(bo); +} + +union gbm_bo_handle +gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_handle_for_plane(bo, plane); +} + +int +gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_fd_for_plane(bo, plane); +} + +int +gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count) +{ + return GbmProxy::Instance()->Api().gbm_bo_write(bo, buf, count); +} + +void +gbm_bo_set_user_data(struct gbm_bo *bo, void *data, + void (*destroy_user_data)(struct gbm_bo *, void *)) +{ + GbmProxy::Instance()->Api().gbm_bo_set_user_data(bo, data, destroy_user_data); +} + +void * +gbm_bo_get_user_data(struct gbm_bo *bo) +{ + return GbmProxy::Instance()->Api().gbm_bo_get_user_data(bo); +} + +void +gbm_bo_destroy(struct gbm_bo *bo) +{ + GbmProxy::Instance()->Api().gbm_bo_destroy(bo); +} + +struct gbm_surface * +gbm_surface_create(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags) +{ + return GbmProxy::Instance()->Api().gbm_surface_create(gbm, width, height, format, flags); +} + +struct gbm_surface * +gbm_surface_create_with_modifiers(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count) +{ + return GbmProxy::Instance()->Api().gbm_surface_create_with_modifiers(gbm, width, height, format, modifiers, count); +} + +struct gbm_surface * +gbm_surface_create_with_modifiers2(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count, + uint32_t flags) +{ + return GbmProxy::Instance()->Api().gbm_surface_create_with_modifiers2(gbm, width, height, format, modifiers, count, flags); +} + +struct gbm_bo * +gbm_surface_lock_front_buffer(struct gbm_surface *surface) +{ + return GbmProxy::Instance()->Api().gbm_surface_lock_front_buffer(surface); +} + +void +gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo) +{ + GbmProxy::Instance()->Api().gbm_surface_release_buffer(surface, bo); +} + +int +gbm_surface_has_free_buffers(struct gbm_surface *surface) +{ + return GbmProxy::Instance()->Api().gbm_surface_has_free_buffers(surface); +} + +void +gbm_surface_destroy(struct gbm_surface *surface) +{ + GbmProxy::Instance()->Api().gbm_surface_destroy(surface); +} + +char * +gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc) +{ + return GbmProxy::Instance()->Api().gbm_format_get_name(gbm_format, desc); +} \ No newline at end of file diff --git a/gralloc_gbm_proxy/gbm.h b/gralloc_gbm_proxy/gbm.h new file mode 100755 index 0000000..1a1e2ca --- /dev/null +++ b/gralloc_gbm_proxy/gbm.h @@ -0,0 +1,469 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Benjamin Franzke + */ + +#ifndef _GBM_H_ +#define _GBM_H_ + +#define __GBM__ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \file gbm.h + * \brief Generic Buffer Manager + */ + +struct gbm_device; +struct gbm_bo; +struct gbm_surface; + +/** + * \mainpage The Generic Buffer Manager + * + * This module provides an abstraction that the caller can use to request a + * buffer from the underlying memory management system for the platform. + * + * This allows the creation of portable code whilst still allowing access to + * the underlying memory manager. + */ + +/** + * Abstraction representing the handle to a buffer allocated by the + * manager + */ +union gbm_bo_handle { + void *ptr; + int32_t s32; + uint32_t u32; + int64_t s64; + uint64_t u64; +}; + +/** Format of the allocated buffer */ +enum gbm_bo_format { + /** RGB with 8 bits per channel in a 32 bit value */ + GBM_BO_FORMAT_XRGB8888, + /** ARGB with 8 bits per channel in a 32 bit value */ + GBM_BO_FORMAT_ARGB8888 +}; + + +/** + * The FourCC format codes are taken from the drm_fourcc.h definition, and + * re-namespaced. New GBM formats must not be added, unless they are + * identical ports from drm_fourcc. + */ +#define __gbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ + ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) + +#define GBM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ + +/* color index */ +#define GBM_FORMAT_C8 __gbm_fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ + +/* 8 bpp Red */ +#define GBM_FORMAT_R8 __gbm_fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ + +/* 16 bpp Red */ +#define GBM_FORMAT_R16 __gbm_fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ + +/* 16 bpp RG */ +#define GBM_FORMAT_GR88 __gbm_fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ + +/* 32 bpp RG */ +#define GBM_FORMAT_RG1616 __gbm_fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */ +#define GBM_FORMAT_GR1616 __gbm_fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */ + +/* 8 bpp RGB */ +#define GBM_FORMAT_RGB332 __gbm_fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ +#define GBM_FORMAT_BGR233 __gbm_fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ + +/* 16 bpp RGB */ +#define GBM_FORMAT_XRGB4444 __gbm_fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */ +#define GBM_FORMAT_XBGR4444 __gbm_fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */ +#define GBM_FORMAT_RGBX4444 __gbm_fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */ +#define GBM_FORMAT_BGRX4444 __gbm_fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */ + +#define GBM_FORMAT_ARGB4444 __gbm_fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */ +#define GBM_FORMAT_ABGR4444 __gbm_fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */ +#define GBM_FORMAT_RGBA4444 __gbm_fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */ +#define GBM_FORMAT_BGRA4444 __gbm_fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */ + +#define GBM_FORMAT_XRGB1555 __gbm_fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */ +#define GBM_FORMAT_XBGR1555 __gbm_fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */ +#define GBM_FORMAT_RGBX5551 __gbm_fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */ +#define GBM_FORMAT_BGRX5551 __gbm_fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */ + +#define GBM_FORMAT_ARGB1555 __gbm_fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */ +#define GBM_FORMAT_ABGR1555 __gbm_fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */ +#define GBM_FORMAT_RGBA5551 __gbm_fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */ +#define GBM_FORMAT_BGRA5551 __gbm_fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */ + +#define GBM_FORMAT_RGB565 __gbm_fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ +#define GBM_FORMAT_BGR565 __gbm_fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */ + +/* 24 bpp RGB */ +#define GBM_FORMAT_RGB888 __gbm_fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ +#define GBM_FORMAT_BGR888 __gbm_fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */ + +/* 32 bpp RGB */ +#define GBM_FORMAT_XRGB8888 __gbm_fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ +#define GBM_FORMAT_XBGR8888 __gbm_fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */ +#define GBM_FORMAT_RGBX8888 __gbm_fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */ +#define GBM_FORMAT_BGRX8888 __gbm_fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */ + +#define GBM_FORMAT_ARGB8888 __gbm_fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */ +#define GBM_FORMAT_ABGR8888 __gbm_fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */ +#define GBM_FORMAT_RGBA8888 __gbm_fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */ +#define GBM_FORMAT_BGRA8888 __gbm_fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */ + +#define GBM_FORMAT_XRGB2101010 __gbm_fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */ +#define GBM_FORMAT_XBGR2101010 __gbm_fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ +#define GBM_FORMAT_RGBX1010102 __gbm_fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */ +#define GBM_FORMAT_BGRX1010102 __gbm_fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */ + +#define GBM_FORMAT_ARGB2101010 __gbm_fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */ +#define GBM_FORMAT_ABGR2101010 __gbm_fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ +#define GBM_FORMAT_RGBA1010102 __gbm_fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ +#define GBM_FORMAT_BGRA1010102 __gbm_fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ + +/* 64 bpp RGB */ +#define GBM_FORMAT_XBGR16161616 __gbm_fourcc_code('X', 'B', '4', '8') /* [63:0] x:B:G:R 16:16:16:16 little endian */ + +#define GBM_FORMAT_ABGR16161616 __gbm_fourcc_code('A', 'B', '4', '8') /* [63:0] A:B:G:R 16:16:16:16 little endian */ + +/* + * Floating point 64bpp RGB + * IEEE 754-2008 binary16 half-precision float + * [15:0] sign:exponent:mantissa 1:5:10 + */ +#define GBM_FORMAT_XBGR16161616F __gbm_fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */ + +#define GBM_FORMAT_ABGR16161616F __gbm_fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */ + +/* packed YCbCr */ +#define GBM_FORMAT_YUYV __gbm_fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ +#define GBM_FORMAT_YVYU __gbm_fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ +#define GBM_FORMAT_UYVY __gbm_fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ +#define GBM_FORMAT_VYUY __gbm_fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ + +#define GBM_FORMAT_AYUV __gbm_fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ + +/* + * 2 plane YCbCr + * index 0 = Y plane, [7:0] Y + * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian + * or + * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian + */ +#define GBM_FORMAT_NV12 __gbm_fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ +#define GBM_FORMAT_NV21 __gbm_fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */ +#define GBM_FORMAT_NV16 __gbm_fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ +#define GBM_FORMAT_NV61 __gbm_fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ + +/* + * 3 plane YCbCr + * index 0: Y plane, [7:0] Y + * index 1: Cb plane, [7:0] Cb + * index 2: Cr plane, [7:0] Cr + * or + * index 1: Cr plane, [7:0] Cr + * index 2: Cb plane, [7:0] Cb + */ +#define GBM_FORMAT_YUV410 __gbm_fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */ +#define GBM_FORMAT_YVU410 __gbm_fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */ +#define GBM_FORMAT_YUV411 __gbm_fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */ +#define GBM_FORMAT_YVU411 __gbm_fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */ +#define GBM_FORMAT_YUV420 __gbm_fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ +#define GBM_FORMAT_YVU420 __gbm_fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */ +#define GBM_FORMAT_YUV422 __gbm_fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */ +#define GBM_FORMAT_YVU422 __gbm_fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ +#define GBM_FORMAT_YUV444 __gbm_fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ +#define GBM_FORMAT_YVU444 __gbm_fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ + +struct gbm_format_name_desc { + char name[5]; +}; + +/** + * Flags to indicate the intended use for the buffer - these are passed into + * gbm_bo_create(). The caller must set the union of all the flags that are + * appropriate + * + * \sa Use gbm_device_is_format_supported() to check if the combination of format + * and use flags are supported + */ +enum gbm_bo_flags { + /** + * Buffer is going to be presented to the screen using an API such as KMS + */ + GBM_BO_USE_SCANOUT = (1 << 0), + /** + * Buffer is going to be used as cursor + */ + GBM_BO_USE_CURSOR = (1 << 1), + /** + * Deprecated + */ + GBM_BO_USE_CURSOR_64X64 = GBM_BO_USE_CURSOR, + /** + * Buffer is to be used for rendering - for example it is going to be used + * as the storage for a color buffer + */ + GBM_BO_USE_RENDERING = (1 << 2), + /** + * Buffer can be used for gbm_bo_write. This is guaranteed to work + * with GBM_BO_USE_CURSOR, but may not work for other combinations. + */ + GBM_BO_USE_WRITE = (1 << 3), + /** + * Buffer is linear, i.e. not tiled. + */ + GBM_BO_USE_LINEAR = (1 << 4), + /** + * Buffer is protected, i.e. encrypted and not readable by CPU or any + * other non-secure / non-trusted components nor by non-trusted OpenGL, + * OpenCL, and Vulkan applications. + */ + GBM_BO_USE_PROTECTED = (1 << 5), + + /** + * The buffer will be used for front buffer rendering. On some + * platforms this may (for example) disable framebuffer compression + * to avoid problems with compression flags data being out of sync + * with pixel data. + */ + GBM_BO_USE_FRONT_RENDERING = (1 << 6), +}; + +int +gbm_device_get_fd(struct gbm_device *gbm); + +const char * +gbm_device_get_backend_name(struct gbm_device *gbm); + +int +gbm_device_is_format_supported(struct gbm_device *gbm, + uint32_t format, uint32_t flags); + +int +gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm, + uint32_t format, + uint64_t modifier); + +void +gbm_device_destroy(struct gbm_device *gbm); + +struct gbm_device * +gbm_create_device(int fd); + +struct gbm_bo * +gbm_bo_create(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags); + +struct gbm_bo * +gbm_bo_create_with_modifiers(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count); + +struct gbm_bo * +gbm_bo_create_with_modifiers2(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count, + uint32_t flags); + +#define GBM_BO_IMPORT_WL_BUFFER 0x5501 +#define GBM_BO_IMPORT_EGL_IMAGE 0x5502 +#define GBM_BO_IMPORT_FD 0x5503 +#define GBM_BO_IMPORT_FD_MODIFIER 0x5504 + +struct gbm_import_fd_data { + int fd; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; +}; + +#define GBM_MAX_PLANES 4 + +struct gbm_import_fd_modifier_data { + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t num_fds; + int fds[GBM_MAX_PLANES]; + int strides[GBM_MAX_PLANES]; + int offsets[GBM_MAX_PLANES]; + uint64_t modifier; +}; + +struct gbm_bo * +gbm_bo_import(struct gbm_device *gbm, uint32_t type, + void *buffer, uint32_t flags); + +/** + * Flags to indicate the type of mapping for the buffer - these are + * passed into gbm_bo_map(). The caller must set the union of all the + * flags that are appropriate. + * + * These flags are independent of the GBM_BO_USE_* creation flags. However, + * mapping the buffer may require copying to/from a staging buffer. + * + * See also: pipe_map_flags + */ +enum gbm_bo_transfer_flags { + /** + * Buffer contents read back (or accessed directly) at transfer + * create time. + */ + GBM_BO_TRANSFER_READ = (1 << 0), + /** + * Buffer contents will be written back at unmap time + * (or modified as a result of being accessed directly). + */ + GBM_BO_TRANSFER_WRITE = (1 << 1), + /** + * Read/modify/write + */ + GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE), +}; + +void * +gbm_bo_map(struct gbm_bo *bo, + uint32_t x, uint32_t y, uint32_t width, uint32_t height, + uint32_t flags, uint32_t *stride, void **map_data); + +void +gbm_bo_unmap(struct gbm_bo *bo, void *map_data); + +uint32_t +gbm_bo_get_width(struct gbm_bo *bo); + +uint32_t +gbm_bo_get_height(struct gbm_bo *bo); + +uint32_t +gbm_bo_get_stride(struct gbm_bo *bo); + +uint32_t +gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane); + +uint32_t +gbm_bo_get_format(struct gbm_bo *bo); + +uint32_t +gbm_bo_get_bpp(struct gbm_bo *bo); + +uint32_t +gbm_bo_get_offset(struct gbm_bo *bo, int plane); + +struct gbm_device * +gbm_bo_get_device(struct gbm_bo *bo); + +union gbm_bo_handle +gbm_bo_get_handle(struct gbm_bo *bo); + +int +gbm_bo_get_fd(struct gbm_bo *bo); + +uint64_t +gbm_bo_get_modifier(struct gbm_bo *bo); + +int +gbm_bo_get_plane_count(struct gbm_bo *bo); + +union gbm_bo_handle +gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane); + +int +gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane); + +int +gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count); + +void +gbm_bo_set_user_data(struct gbm_bo *bo, void *data, + void (*destroy_user_data)(struct gbm_bo *, void *)); + +void * +gbm_bo_get_user_data(struct gbm_bo *bo); + +void +gbm_bo_destroy(struct gbm_bo *bo); + +struct gbm_surface * +gbm_surface_create(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags); + +struct gbm_surface * +gbm_surface_create_with_modifiers(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count); + +struct gbm_surface * +gbm_surface_create_with_modifiers2(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count, + uint32_t flags); + +struct gbm_bo * +gbm_surface_lock_front_buffer(struct gbm_surface *surface); + +void +gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo); + +int +gbm_surface_has_free_buffers(struct gbm_surface *surface); + +void +gbm_surface_destroy(struct gbm_surface *surface); + +char * +gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gralloc_gbm_proxy/gbm_proxy.cpp b/gralloc_gbm_proxy/gbm_proxy.cpp new file mode 100755 index 0000000..681b65f --- /dev/null +++ b/gralloc_gbm_proxy/gbm_proxy.cpp @@ -0,0 +1,141 @@ +#include "gbm_proxy.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +constexpr char kGbmLibName[] = "libgbm_mesa_proxy.so.1"; // soname +constexpr char kGbmLibEnvName[] = "HYBRIS-EGL"; + +bool GbmProxy::Initialize() { + if (!handle_) { + return false; + } + InitializeApi(); + return true; +} + +GbmProxyPtr &GbmProxy::Instance() { + static bool inited = false; + static GbmProxyPtr gbm{}; + static std::mutex mtx{}; + if (!inited) { + std::lock_guard guard{mtx}; + if (!inited) { + gbm = Load(); + std::atomic_thread_fence(std::memory_order::memory_order_release); + inited = true; + } + } + if (!gbm) { + ALOGE("Load and initialize gbm proxy failed"); + // abort(); + } + return gbm; +} + +GbmProxyPtr GbmProxy::Load() { + if (auto gbm_handle = LoadLibrary(); gbm_handle) { + if (auto gbm = std::make_shared(gbm_handle); gbm->Initialize()) { + return gbm; + } + } + return nullptr; +} + +std::shared_ptr GbmProxy::LoadLibrary() { + const char *env_name = getenv(kGbmLibEnvName); + auto name = env_name ? env_name : kGbmLibName; + return LoadLibrary(name); +} + +std::shared_ptr GbmProxy::LoadLibrary(const char *name) { + if (auto handle = dlopen(name, RTLD_LOCAL); handle) { + return std::shared_ptr(handle, [](void *h) { + if (h) { + dlclose(h); + } + }); + } + ALOGE("dlopen %s failed: %s", name, dlerror()); + return nullptr; +} + +void GbmProxy::InitializeApi() { + assert(handle_); + // init api symbols + auto handle = handle_.get(); + auto &api = api_; + +#define GETSYMBOLADDR(symbol) \ + do { \ + api.symbol = \ + reinterpret_cast(dlsym(handle, #symbol)); \ + } while (0) + + GETSYMBOLADDR(gbm_device_get_fd); + GETSYMBOLADDR(gbm_create_device); + GETSYMBOLADDR(gbm_device_get_backend_name); + GETSYMBOLADDR(gbm_device_is_format_supported); + GETSYMBOLADDR(gbm_device_get_format_modifier_plane_count); + GETSYMBOLADDR(gbm_device_destroy); + + GETSYMBOLADDR(gbm_bo_create); + GETSYMBOLADDR(gbm_bo_create_with_modifiers); + GETSYMBOLADDR(gbm_bo_create_with_modifiers2); + GETSYMBOLADDR(gbm_bo_import); + + GETSYMBOLADDR(gbm_bo_map); + GETSYMBOLADDR(gbm_bo_unmap); + + GETSYMBOLADDR(gbm_bo_get_width); + GETSYMBOLADDR(gbm_bo_get_height); + GETSYMBOLADDR(gbm_bo_get_stride); + GETSYMBOLADDR(gbm_bo_get_stride_for_plane); + GETSYMBOLADDR(gbm_bo_get_format); + GETSYMBOLADDR(gbm_bo_get_bpp); + GETSYMBOLADDR(gbm_bo_get_offset); + GETSYMBOLADDR(gbm_bo_get_device); + + GETSYMBOLADDR(gbm_bo_get_handle); + GETSYMBOLADDR(gbm_bo_get_fd); + GETSYMBOLADDR(gbm_bo_get_modifier); + GETSYMBOLADDR(gbm_bo_get_plane_count); + GETSYMBOLADDR(gbm_bo_get_handle_for_plane); + GETSYMBOLADDR(gbm_bo_get_fd_for_plane); + + GETSYMBOLADDR(gbm_bo_write); + GETSYMBOLADDR(gbm_bo_set_user_data); + GETSYMBOLADDR(gbm_bo_get_user_data); + GETSYMBOLADDR(gbm_bo_destroy); + + GETSYMBOLADDR(gbm_surface_create); + GETSYMBOLADDR(gbm_surface_create_with_modifiers); + GETSYMBOLADDR(gbm_surface_create_with_modifiers2); + GETSYMBOLADDR(gbm_surface_lock_front_buffer); + GETSYMBOLADDR(gbm_surface_release_buffer); + GETSYMBOLADDR(gbm_surface_has_free_buffers); + GETSYMBOLADDR(gbm_surface_destroy); + + GETSYMBOLADDR(gbm_format_get_name); + +#undef GETSYMBOLADDR +} + diff --git a/gralloc_gbm_proxy/gbm_proxy.h b/gralloc_gbm_proxy/gbm_proxy.h new file mode 100755 index 0000000..921c3c1 --- /dev/null +++ b/gralloc_gbm_proxy/gbm_proxy.h @@ -0,0 +1,129 @@ +#ifndef _GBM_PROXY_H_ +#define _GBM_PROXY_H_ + +#include "gbm.h" + +#include +#include + +typedef int (*gbm_device_get_fd_t)(struct gbm_device *); +typedef struct gbm_device *(*gbm_create_device_t)(int); + +typedef void *(*gbm_bo_get_user_data_t)(struct gbm_bo *); +typedef const char *(*gbm_device_get_backend_name_t)(struct gbm_device *); +typedef int (*gbm_device_is_format_supported_t)(struct gbm_device *, uint32_t, uint32_t); +typedef int (*gbm_device_get_format_modifier_plane_count_t)(struct gbm_device *, uint32_t, uint64_t); +typedef void (*gbm_device_destroy_t)(struct gbm_device *); + +typedef struct gbm_bo *(*gbm_bo_create_t)(struct gbm_device *, uint32_t, uint32_t, uint32_t, uint32_t); +typedef struct gbm_bo *(*gbm_bo_create_with_modifiers_t)(struct gbm_device *, uint32_t, uint32_t, uint32_t, const uint64_t *, const unsigned int); +typedef struct gbm_bo *(*gbm_bo_create_with_modifiers2_t)(struct gbm_device *, uint32_t, uint32_t, uint32_t, const uint64_t *, const unsigned int, uint32_t); +typedef struct gbm_bo *(*gbm_bo_import_t)(struct gbm_device *, uint32_t, void *, uint32_t); + +typedef void *(*gbm_bo_map_t)(struct gbm_bo *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t *, void **); +typedef void (*gbm_bo_unmap_t)(struct gbm_bo *, void *); + +typedef uint32_t (*gbm_bo_get_width_t)(struct gbm_bo *); +typedef uint32_t (*gbm_bo_get_height_t)(struct gbm_bo *); +typedef uint32_t (*gbm_bo_get_stride_t)(struct gbm_bo *); +typedef uint32_t (*gbm_bo_get_stride_for_plane_t)(struct gbm_bo *, int); +typedef uint32_t (*gbm_bo_get_format_t)(struct gbm_bo *); +typedef uint32_t (*gbm_bo_get_bpp_t)(struct gbm_bo *); +typedef uint32_t (*gbm_bo_get_offset_t)(struct gbm_bo *, int); +typedef struct gbm_device *(*gbm_bo_get_device_t)(struct gbm_bo *); + +typedef union gbm_bo_handle (*gbm_bo_get_handle_t)(struct gbm_bo *); +typedef int (*gbm_bo_get_fd_t)(struct gbm_bo *); +typedef uint64_t (*gbm_bo_get_modifier_t)(struct gbm_bo *); +typedef int (*gbm_bo_get_plane_count_t)(struct gbm_bo *); +typedef union gbm_bo_handle (*gbm_bo_get_handle_for_plane_t)(struct gbm_bo *, int); +typedef int (*gbm_bo_get_fd_for_plane_t)(struct gbm_bo *, int); +typedef int (*gbm_bo_write_t)(struct gbm_bo *, const void *, size_t); +typedef void (*gbm_bo_set_user_data_t)(struct gbm_bo *, void *, void (*)(struct gbm_bo *, void *)); +typedef void (*gbm_bo_destroy_t)(struct gbm_bo *); + +typedef struct gbm_surface *(*gbm_surface_create_t)(struct gbm_device *, uint32_t, uint32_t, uint32_t, uint32_t); +typedef struct gbm_surface *(*gbm_surface_create_with_modifiers_t)(struct gbm_device *, uint32_t, uint32_t, uint32_t, const uint64_t *, const unsigned int); +typedef struct gbm_surface *(*gbm_surface_create_with_modifiers2_t)(struct gbm_device *, uint32_t, uint32_t, uint32_t, const uint64_t *, const unsigned int, uint32_t); +typedef struct gbm_bo *(*gbm_surface_lock_front_buffer_t)(struct gbm_surface *); +typedef void (*gbm_surface_release_buffer_t)(struct gbm_surface *, struct gbm_bo *); +typedef int (*gbm_surface_has_free_buffers_t)(struct gbm_surface *); +typedef void (*gbm_surface_destroy_t)(struct gbm_surface *); + +typedef char *(*gbm_format_get_name_t)(uint32_t, struct gbm_format_name_desc *); + +struct GbmApi { + gbm_device_get_fd_t gbm_device_get_fd = nullptr; + gbm_create_device_t gbm_create_device = nullptr; + + gbm_bo_get_user_data_t gbm_bo_get_user_data = nullptr; + gbm_device_get_backend_name_t gbm_device_get_backend_name = nullptr; + gbm_device_is_format_supported_t gbm_device_is_format_supported = nullptr; + gbm_device_get_format_modifier_plane_count_t gbm_device_get_format_modifier_plane_count = nullptr; + gbm_device_destroy_t gbm_device_destroy = nullptr; + + gbm_bo_create_t gbm_bo_create = nullptr; + gbm_bo_create_with_modifiers_t gbm_bo_create_with_modifiers = nullptr; + gbm_bo_create_with_modifiers2_t gbm_bo_create_with_modifiers2 = nullptr; + gbm_bo_import_t gbm_bo_import = nullptr; + + gbm_bo_map_t gbm_bo_map = nullptr; + gbm_bo_unmap_t gbm_bo_unmap = nullptr; + + gbm_bo_get_width_t gbm_bo_get_width = nullptr; + gbm_bo_get_height_t gbm_bo_get_height = nullptr; + gbm_bo_get_stride_t gbm_bo_get_stride = nullptr; + gbm_bo_get_stride_for_plane_t gbm_bo_get_stride_for_plane = nullptr; + gbm_bo_get_format_t gbm_bo_get_format = nullptr; + gbm_bo_get_bpp_t gbm_bo_get_bpp = nullptr; + gbm_bo_get_offset_t gbm_bo_get_offset = nullptr; + gbm_bo_get_device_t gbm_bo_get_device = nullptr; + + gbm_bo_get_handle_t gbm_bo_get_handle = nullptr; + gbm_bo_get_fd_t gbm_bo_get_fd = nullptr; + gbm_bo_get_modifier_t gbm_bo_get_modifier = nullptr; + gbm_bo_get_plane_count_t gbm_bo_get_plane_count = nullptr; + gbm_bo_get_handle_for_plane_t gbm_bo_get_handle_for_plane = nullptr; + gbm_bo_get_fd_for_plane_t gbm_bo_get_fd_for_plane = nullptr; + gbm_bo_write_t gbm_bo_write = nullptr; + gbm_bo_set_user_data_t gbm_bo_set_user_data = nullptr; + gbm_bo_destroy_t gbm_bo_destroy = nullptr; + + gbm_surface_create_t gbm_surface_create = nullptr; + gbm_surface_create_with_modifiers_t gbm_surface_create_with_modifiers = nullptr; + gbm_surface_create_with_modifiers2_t gbm_surface_create_with_modifiers2 = nullptr; + gbm_surface_lock_front_buffer_t gbm_surface_lock_front_buffer = nullptr; + gbm_surface_release_buffer_t gbm_surface_release_buffer = nullptr; + gbm_surface_has_free_buffers_t gbm_surface_has_free_buffers = nullptr; + gbm_surface_destroy_t gbm_surface_destroy = nullptr; + + gbm_format_get_name_t gbm_format_get_name = nullptr; +}; + +class GbmProxy; +using GbmProxyPtr = std::shared_ptr; + +class GbmProxy { + +public: + static GbmProxyPtr &Instance(); + + GbmProxy(std::shared_ptr handle) : handle_(std::move(handle)) {} + + bool Initialize(); + + const GbmApi &Api() const { return api_; } + + static std::shared_ptr LoadLibrary(); + static std::shared_ptr LoadLibrary(const char *name); + + private: + void InitializeApi(); + + static GbmProxyPtr Load(); + + GbmApi api_{}; + std::shared_ptr handle_ = {}; +}; + +#endif diff --git a/gralloc_gbm_proxy/gralloc.cpp b/gralloc_gbm_proxy/gralloc.cpp new file mode 100755 index 0000000..0798003 --- /dev/null +++ b/gralloc_gbm_proxy/gralloc.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2010-2011 Chia-I Wu + * Copyright (C) 2010-2011 LunarG Inc. + * Copyright (C) 2016 Linaro, Ltd., Rob Herring + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#define LOG_TAG "GRALLOC-GBM-PROXY" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "gbm.h" + +#include "gralloc_drm.h" +#include "gralloc_gbm_priv.h" + +#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4 + +struct cros_gralloc0_buffer_info { + uint32_t drm_fourcc; + int num_fds; + int fds[4]; + uint64_t modifier; + int offset[4]; + int stride[4]; +}; + +struct gbm_module_t { + gralloc_module_t base; + + pthread_mutex_t mutex; + struct gbm_device *gbm; +}; + +/* + * Initialize the DRM device object + */ +static int gbm_init(struct gbm_module_t *dmod) +{ + int err = 0; + + pthread_mutex_lock(&dmod->mutex); + if (!dmod->gbm) { + dmod->gbm = gbm_dev_create(); + if (!dmod->gbm) + err = -EINVAL; + } + pthread_mutex_unlock(&dmod->mutex); + + return err; +} + +static int get_fourcc(int format) +{ + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + return DRM_FORMAT_ABGR8888; + case HAL_PIXEL_FORMAT_RGBX_8888: + return DRM_FORMAT_XBGR8888; + case HAL_PIXEL_FORMAT_RGB_888: + return DRM_FORMAT_BGR888; + case HAL_PIXEL_FORMAT_RGB_565: + return DRM_FORMAT_RGB565; + case HAL_PIXEL_FORMAT_BGRA_8888: + return DRM_FORMAT_ARGB8888; + case HAL_PIXEL_FORMAT_YV12: + /* YV12 is planar, but must be a single buffer so ask for GR88 */ + return DRM_FORMAT_GR88; + case HAL_PIXEL_FORMAT_RGBA_FP16: + return DRM_FORMAT_ABGR16161616F; + case HAL_PIXEL_FORMAT_RGBA_1010102: + return DRM_FORMAT_ABGR2101010; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + default: + return 0; + } +} + +static int gbm_mod_perform(const struct gralloc_module_t *mod, int op, ...) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + va_list args; + int err; + uint32_t uop = static_cast(op); + buffer_handle_t handle; + struct cros_gralloc0_buffer_info *info; + struct gralloc_handle_t *hnd; + + err = gbm_init(dmod); + if (err) + return err; + + va_start(args, op); + switch (uop) { + case GRALLOC_MODULE_PERFORM_GET_DRM_FD: + { + int *fd = va_arg(args, int *); + *fd = gbm_device_get_fd(dmod->gbm); + err = 0; + } + break; + case CROS_GRALLOC_DRM_GET_BUFFER_INFO: + { + handle = va_arg(args, buffer_handle_t); + hnd = gralloc_handle(handle); + info = va_arg(args, struct cros_gralloc0_buffer_info *); + memset(info, 0, sizeof(*info)); + info->drm_fourcc = get_fourcc(hnd->format); + info->num_fds = 1; + info->fds[0] = hnd->prime_fd; + info->modifier = hnd->modifier; + info->stride[0] = hnd->stride; + info->offset[0] = 0; + err = 0; + } + break; + default: + err = -EINVAL; + break; + } + va_end(args); + + return err; +} + +static int gbm_mod_register_buffer(const gralloc_module_t *mod, + buffer_handle_t handle) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + int err; + + err = gbm_init(dmod); + if (err) + return err; + + pthread_mutex_lock(&dmod->mutex); + err = gralloc_gbm_handle_register(handle, dmod->gbm); + pthread_mutex_unlock(&dmod->mutex); + + return err; +} + +static int gbm_mod_unregister_buffer(const gralloc_module_t *mod, + buffer_handle_t handle) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + int err; + + pthread_mutex_lock(&dmod->mutex); + err = gralloc_gbm_handle_unregister(handle); + pthread_mutex_unlock(&dmod->mutex); + + return err; +} + +static int gbm_mod_need_convert_format(const gralloc_module_t *mod, buffer_handle_t handle) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + int err; + + pthread_mutex_lock(&dmod->mutex); + err = gralloc_gbm_need_convert_format(handle); + pthread_mutex_unlock(&dmod->mutex); + + return err; +} + +static int gbm_mod_lock(const gralloc_module_t *mod, buffer_handle_t handle, + int usage, int x, int y, int w, int h, void **ptr) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + int err; + + pthread_mutex_lock(&dmod->mutex); + + err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, ptr); + ALOGV("buffer %p lock usage = %08x", handle, usage); + + pthread_mutex_unlock(&dmod->mutex); + return err; +} + +static int gbm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + int err; + + pthread_mutex_lock(&dmod->mutex); + err = gralloc_gbm_bo_unlock(handle); + pthread_mutex_unlock(&dmod->mutex); + + return err; +} + +static int gbm_mod_lock_ycbcr(gralloc_module_t const *mod, buffer_handle_t handle, + int usage, int x, int y, int w, int h, struct android_ycbcr *ycbcr) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + int err; + + pthread_mutex_lock(&dmod->mutex); + err = gralloc_gbm_bo_lock_ycbcr(handle, usage, x, y, w, h, ycbcr); + pthread_mutex_unlock(&dmod->mutex); + + return err; +} + +static int gbm_mod_close_gpu0(struct hw_device_t *dev) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *)dev->module; + struct alloc_device_t *alloc = (struct alloc_device_t *) dev; + + gbm_dev_destroy(dmod->gbm); + delete alloc; + + return 0; +} + +static int gbm_mod_free_gpu0(alloc_device_t *dev, buffer_handle_t handle) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) dev->common.module; + + pthread_mutex_lock(&dmod->mutex); + gbm_free(handle); + native_handle_close(handle); + delete handle; + + pthread_mutex_unlock(&dmod->mutex); + return 0; +} + +static int gbm_mod_alloc_gpu0(alloc_device_t *dev, + int w, int h, int format, int usage, + buffer_handle_t *handle, int *stride) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) dev->common.module; + int err = 0; + + pthread_mutex_lock(&dmod->mutex); + + *handle = gralloc_gbm_bo_create(dmod->gbm, w, h, format, usage, stride); + if (!*handle) + err = -errno; + + ALOGV("buffer %p usage = %08x", *handle, usage); + pthread_mutex_unlock(&dmod->mutex); + return err; +} + +static int gbm_mod_open_gpu0(struct gbm_module_t *dmod, hw_device_t **dev) +{ + struct alloc_device_t *alloc; + int err; + + err = gbm_init(dmod); + if (err) + return err; + + alloc = new alloc_device_t(); + if (!alloc) + return -EINVAL; + + alloc->common.tag = HARDWARE_DEVICE_TAG; + alloc->common.version = 0; + alloc->common.module = &dmod->base.common; + alloc->common.close = gbm_mod_close_gpu0; + + alloc->alloc = gbm_mod_alloc_gpu0; + alloc->free = gbm_mod_free_gpu0; + + *dev = &alloc->common; + + return 0; +} + +static int gbm_mod_open(const struct hw_module_t *mod, + const char *name, struct hw_device_t **dev) +{ + struct gbm_module_t *dmod = (struct gbm_module_t *) mod; + int err; + + if (strcmp(name, GRALLOC_HARDWARE_GPU0) == 0) + err = gbm_mod_open_gpu0(dmod, dev); + else + err = -EINVAL; + + return err; +} + +static struct hw_module_methods_t gbm_mod_methods = { + .open = gbm_mod_open +}; + +struct gbm_module_t HAL_MODULE_INFO_SYM = { + .base = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = GRALLOC_HARDWARE_MODULE_ID, + .name = "GBM Memory Allocator", + .author = "Rob Herring - Linaro", + .methods = &gbm_mod_methods + }, + .registerBuffer = gbm_mod_register_buffer, + .unregisterBuffer = gbm_mod_unregister_buffer, + .lock = gbm_mod_lock, + .unlock = gbm_mod_unlock, + .perform = gbm_mod_perform, + .lock_ycbcr = gbm_mod_lock_ycbcr, + .need_convert_format = gbm_mod_need_convert_format + }, + + .mutex = PTHREAD_MUTEX_INITIALIZER, + .gbm = NULL, +}; diff --git a/gralloc_gbm_proxy/gralloc_drm.h b/gralloc_gbm_proxy/gralloc_drm.h new file mode 100755 index 0000000..0ece652 --- /dev/null +++ b/gralloc_gbm_proxy/gralloc_drm.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010-2011 Chia-I Wu + * Copyright (C) 2010-2011 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _GRALLOC_DRM_H_ +#define _GRALLOC_DRM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* perform(const struct gralloc_module_t *mod, + * int op, + * int *fd); + */ + GRALLOC_MODULE_PERFORM_GET_DRM_FD = 0x40000002, +}; + +#ifdef __cplusplus +} +#endif +#endif /* _GRALLOC_DRM_H_ */ diff --git a/gralloc_gbm_proxy/gralloc_gbm.cpp b/gralloc_gbm_proxy/gralloc_gbm.cpp new file mode 100755 index 0000000..beef752 --- /dev/null +++ b/gralloc_gbm_proxy/gralloc_gbm.cpp @@ -0,0 +1,647 @@ +/* + * Copyright (C) 2010-2011 Chia-I Wu + * Copyright (C) 2010-2011 LunarG Inc. + * Copyright (C) 2016 Linaro, Ltd., Rob Herring + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#define LOG_TAG "GRALLOC-GBM-PROXY" +//#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "gbm.h" + +#include "gralloc_gbm_priv.h" +#include + +#include +#include +#include +#include + +#define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) +int align_x = 256; + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#define unlikely(x) __builtin_expect(!!(x), 0) + +static std::unordered_map gbm_bo_handle_map; +static std::unordered_map> gbm_format_modifiers_map; + +struct bo_data_t { + void *map_data; + int lock_count; + int locked_for; +}; + +void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data) +{ + struct bo_data_t *bo_data = (struct bo_data_t *)data; + delete bo_data; + + (void)bo; +} + +static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) { + return (struct bo_data_t *)gbm_bo_get_user_data(bo); +} + + +static std::vector get_supported_modifiers(struct gbm_device *gbm, uint32_t format) { + if (gbm_format_modifiers_map.find(format) != gbm_format_modifiers_map.end()) { + return gbm_format_modifiers_map[format]; + } + + // Create empty default so we can match it next time + std::vector &modifiers = gbm_format_modifiers_map[format]; + + std::stringstream prop_name_stream; + prop_name_stream << "openfde.modifiers." << std::hex << format << "."; + std::string prop_name_base = prop_name_stream.str(); + char modifier_prop[PROPERTY_VALUE_MAX]; + int i = 0; + while (true) { + std::string prop_name = (std::stringstream() << prop_name_base << i).str(); + if (property_get(prop_name.c_str(), modifier_prop, NULL) < 1) + break; + std::stringstream ss(modifier_prop); + uint64_t mod; + ss >> std::hex >> mod; + + // Filter out multiplanar format-modifier combos + if (gbm_device_get_format_modifier_plane_count(gbm, format, mod) < 2) + modifiers.push_back(mod); + i++; + } + + return modifiers; +} + +static uint32_t get_gbm_format(int format) +{ + uint32_t fmt; + + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + if (property_get_bool("persist.openfde.invert_colors", false)) + fmt = GBM_FORMAT_ARGB8888; + else + fmt = GBM_FORMAT_ABGR8888; + break; + case HAL_PIXEL_FORMAT_RGBX_8888: + fmt = GBM_FORMAT_XBGR8888; + break; + case HAL_PIXEL_FORMAT_RGB_888: + fmt = GBM_FORMAT_RGB888; + break; + case HAL_PIXEL_FORMAT_RGB_565: + fmt = GBM_FORMAT_RGB565; + break; + case HAL_PIXEL_FORMAT_BGRA_8888: + if (property_get_bool("persist.openfde.invert_colors", false)) + fmt = GBM_FORMAT_ABGR8888; + else + fmt = GBM_FORMAT_ARGB8888; + break; + case HAL_PIXEL_FORMAT_YV12: + /* YV12 is planar, but must be a single buffer so ask for RGB565 */ + fmt = GBM_FORMAT_RGB565; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_888: + /* YV12 is planar, but must be a single buffer so ask for RGB565 */ + fmt = GBM_FORMAT_RGB565; + break; + case HAL_PIXEL_FORMAT_RGBA_FP16: + fmt = GBM_FORMAT_ABGR16161616F; + break; + case HAL_PIXEL_FORMAT_RGBA_1010102: + fmt = GBM_FORMAT_ABGR2101010; + break; + case HAL_PIXEL_FORMAT_BLOB: + fmt = GBM_FORMAT_RGB565; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + default: + fmt = 0; + break; + } + + return fmt; +} + +static int gralloc_gbm_get_bpp(int format) +{ + int bpp; + + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_FP16: + bpp = 8; + break; + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBA_1010102: + bpp = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + bpp = 2; + break; + /* planar; only Y is considered */ + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_888: + bpp = 1; + break; + default: + bpp = 0; + break; + } + + return bpp; +} + +static unsigned int get_pipe_bind(int usage) +{ + unsigned int bind = 0; + + if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)) + bind |= GBM_BO_USE_LINEAR; + if (usage & GRALLOC_USAGE_CURSOR) + ;//bind |= GBM_BO_USE_CURSOR; + if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE)) + bind |= GBM_BO_USE_RENDERING; + if (usage & GRALLOC_USAGE_HW_FB) + bind |= GBM_BO_USE_RENDERING; + if (usage & GRALLOC_USAGE_HW_COMPOSER) + bind |= GBM_BO_USE_RENDERING; + + return bind; +} + +static std::pair find_closest_size(int blob) { + if (blob <= 0) { + return {0, 0}; + } + + int width = static_cast(std::sqrt(blob)); + int height = width = ((width + 7) / 8) * 8; + + while (true) { + if (width * height == blob) { + return {width, height}; + } else if (width * height < blob) { + return {width, height + 1}; + } + height--; + } +} + +static struct gbm_bo *gbm_import(struct gbm_device *gbm, + buffer_handle_t _handle) +{ + struct gbm_bo *bo; + struct gralloc_handle_t *handle = gralloc_handle(_handle); + #ifdef GBM_BO_IMPORT_FD_MODIFIER + struct gbm_import_fd_modifier_data data; + #else + struct gbm_import_fd_data data; + #endif + + int format = get_gbm_format(handle->format); + if (handle->prime_fd < 0) + return NULL; + + memset(&data, 0, sizeof(data)); + data.width = handle->width; + data.height = handle->height; + data.format = format; + /* Adjust the width and height for a GBM GR88 buffer */ + if (handle->format == HAL_PIXEL_FORMAT_YV12 || handle->format == HAL_PIXEL_FORMAT_YCbCr_420_888) { + data.width = GRALLOC_ALIGN(data.width/2, align_x); + data.height += handle->height / 2; + } + if (handle->format == HAL_PIXEL_FORMAT_BLOB) { + std::pair size = find_closest_size(data.width); + data.width = size.first; + data.height = size.second; + } + #ifdef GBM_BO_IMPORT_FD_MODIFIER + data.num_fds = 1; + data.fds[0] = handle->prime_fd; + data.strides[0] = handle->stride; + data.modifier = handle->modifier; + bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, 0); + #else + data.fd = handle->prime_fd; + data.stride = handle->stride; + bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0); + #endif + + if (!bo) { + ALOGE("failed to import BO, size=%dx%d, fmt=%d", + handle->width, handle->height, handle->format); + } + + return bo; +} + +static struct gbm_bo *gbm_alloc(struct gbm_device *gbm, + buffer_handle_t _handle) +{ + struct gbm_bo *bo = NULL; + struct gralloc_handle_t *handle = gralloc_handle(_handle); + int format = get_gbm_format(handle->format); + int usage = get_pipe_bind(handle->usage); + int width, height; + + handle->convert_format = 0; + width = handle->width; + height = handle->height; + if (usage & GBM_BO_USE_CURSOR) { + if (handle->width < 64) + width = 64; + if (handle->height < 64) + height = 64; + } + + /* + * For YV12, we request GR88, so halve the width since we're getting + * 16bpp. Then increase the height by 1.5 for the U and V planes. + */ + if (handle->format == HAL_PIXEL_FORMAT_YV12 || handle->format == HAL_PIXEL_FORMAT_YCbCr_420_888) { + if (width != GRALLOC_ALIGN(width, align_x * 2)) { + width = GRALLOC_ALIGN(width/2, align_x); + if (format == GBM_FORMAT_RGB565) { + handle->convert_format = 1; + } + } else { + width /= 2; + } + height += handle->height / 2; + } + + if (handle->format == HAL_PIXEL_FORMAT_BLOB) { + std::pair size = find_closest_size(width); + width = size.first; + height = size.second; + } + ALOGV("create BO, size=%dx%d, fmt=%d, usage=%x", + handle->width, handle->height, handle->format, usage); + std::vector modifiers = get_supported_modifiers(gbm, format); + if (modifiers.size() > 0) { + bo = gbm_bo_create_with_modifiers(gbm, width, height, format, modifiers.data(), modifiers.size()); + } + if (!bo) { + ALOGV("fallback to gbm_bo_create without modifiers"); + bo = gbm_bo_create(gbm, width, height, format, usage); + } + if (!bo) { + ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x", + handle->width, handle->height, handle->format, usage); + return NULL; + } + + handle->prime_fd = gbm_bo_get_fd(bo); + handle->stride = gbm_bo_get_stride(bo); + #ifdef GBM_BO_IMPORT_FD_MODIFIER + handle->modifier = gbm_bo_get_modifier(bo); + #endif + + return bo; +} + +void gbm_free(buffer_handle_t handle) +{ + struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle); + + if (!bo) + return; + + gbm_bo_handle_map.erase(handle); + gbm_bo_destroy(bo); +} + +/* + * Return the bo of a registered handle. + */ +struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle) +{ + return gbm_bo_handle_map[handle]; +} + +static int gbm_map(buffer_handle_t handle, int enable_write, void **addr) +{ + int err = 0; + int flags = GBM_BO_TRANSFER_READ; + struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle); + struct bo_data_t *bo_data = gbm_bo_data(bo); + uint32_t stride; + + if (bo_data->map_data) + return -EINVAL; + + if (enable_write) + flags |= GBM_BO_TRANSFER_WRITE; + + *addr = gbm_bo_map(bo, 0, 0, gbm_bo_get_width(bo), gbm_bo_get_height(bo), + flags, &stride, &bo_data->map_data); + ALOGV("mapped bo %p at %p", bo, *addr); + if (*addr == NULL) + return -ENOMEM; + + assert(stride == gbm_bo_get_stride(bo)); + + return err; +} + +static void gbm_unmap(struct gbm_bo *bo) +{ + struct bo_data_t *bo_data = gbm_bo_data(bo); + + gbm_bo_unmap(bo, bo_data->map_data); + bo_data->map_data = NULL; +} + +void gbm_dev_destroy(struct gbm_device *gbm) +{ + int fd = gbm_device_get_fd(gbm); + + gbm_device_destroy(gbm); + close(fd); +} + +struct gbm_device *gbm_dev_create(void) +{ + struct gbm_device *gbm; + char path[PROPERTY_VALUE_MAX]; + int fd; + + property_get("gralloc.gbm.device", path, "/dev/dri/renderD128"); + fd = open(path, O_RDWR | O_CLOEXEC); + if (fd < 0) { + ALOGE("failed to open %s", path); + return NULL; + } + + gbm = gbm_create_device(fd); + if (!gbm) { + ALOGE("failed to create gbm device"); + close(fd); + } + + char egl_type[PROPERTY_VALUE_MAX]; + property_get("ro.hardware.egl", egl_type, "none"); + if (strcmp(egl_type, "mesa") == 0) { + align_x = 256; + } else if (strcmp(egl_type, "FTG340") == 0) { + align_x = 32; + } + + return gbm; +} + +/* + * Register a buffer handle. + */ +int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm) +{ + struct gbm_bo *bo; + + if (!_handle) + return -EINVAL; + + if (gbm_bo_handle_map.count(_handle)) + return -EINVAL; + + bo = gbm_import(gbm, _handle); + if (!bo) + return -EINVAL; + + gbm_bo_handle_map.emplace(_handle, bo); + + return 0; +} + +/* + * Unregister a buffer handle. It is no-op for handles created locally. + */ +int gralloc_gbm_handle_unregister(buffer_handle_t handle) +{ + gbm_free(handle); + + return 0; +} + +/* + * Create a bo. + */ +buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm, + int width, int height, int format, int usage, int *stride) +{ + struct gbm_bo *bo; + native_handle_t *handle; + + handle = gralloc_handle_create(width, height, format, usage); + if (!handle) + return NULL; + + bo = gbm_alloc(gbm, handle); + if (!bo) { + native_handle_delete(handle); + return NULL; + } + + gbm_bo_handle_map.emplace(handle, bo); + + /* in pixels */ + *stride = gralloc_handle(handle)->stride / gralloc_gbm_get_bpp(format); + + return handle; +} + +/* + * Lock a bo. XXX thread-safety? + */ +int gralloc_gbm_bo_lock(buffer_handle_t handle, + int usage, int /*x*/, int /*y*/, int /*w*/, int /*h*/, + void **addr) +{ + struct gralloc_handle_t *gbm_handle = gralloc_handle(handle); + struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle); + struct bo_data_t *bo_data; + + if (!bo) + return -EINVAL; + + if ((gbm_handle->usage & usage) != (uint32_t)usage) { + /* make FB special for testing software renderer with */ + + if (!(gbm_handle->usage & ( + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_HW_FB | + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_HW_VIDEO_ENCODER))) { + + ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_{FB,TEXTURE,VIDEO_ENCODER}", + gbm_handle->usage, usage); + return -EINVAL; + } + } + + bo_data = gbm_bo_data(bo); + if (!bo_data) { + bo_data = new struct bo_data_t(); + gbm_bo_set_user_data(bo, bo_data, gralloc_gbm_destroy_user_data); + } + + ALOGV("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage); + + /* allow multiple locks with compatible usages */ + if (bo_data->lock_count && (bo_data->locked_for & usage) != usage) + return -EINVAL; + + usage |= bo_data->locked_for; + + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | + GRALLOC_USAGE_SW_READ_MASK)) { + /* the driver is supposed to wait for the bo */ + int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK); + int err = gbm_map(handle, write, addr); + if (err) + return err; + } + else { + /* kernel handles the synchronization here */ + } + + bo_data->lock_count++; + bo_data->locked_for |= usage; + + return 0; +} + +/* + * Unlock a bo. + */ +int gralloc_gbm_bo_unlock(buffer_handle_t handle) +{ + struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle); + struct bo_data_t *bo_data; + if (!bo) + return -EINVAL; + + bo_data = gbm_bo_data(bo); + + int mapped = bo_data->locked_for & + (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK); + + if (!bo_data->lock_count) + return 0; + + if (mapped) + gbm_unmap(bo); + + bo_data->lock_count--; + if (!bo_data->lock_count) + bo_data->locked_for = 0; + + return 0; +} + +int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle, + int usage, int x, int y, int w, int h, + struct android_ycbcr *ycbcr) +{ + struct gralloc_handle_t *hnd = gralloc_handle(handle); + int ystride, cstride; + void *addr = 0; + int err; + + ALOGV("handle %p, hnd %p, usage 0x%x", handle, hnd, usage); + + err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, &addr); + if (err) + return err; + + memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved)); + + switch (hnd->format) { + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + ystride = cstride = GRALLOC_ALIGN(hnd->width, 16); + ycbcr->y = addr; + ycbcr->cr = (unsigned char *)addr + ystride * hnd->height; + ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + 1; + ycbcr->ystride = ystride; + ycbcr->cstride = cstride; + ycbcr->chroma_step = 2; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_888: + ystride = cstride = GRALLOC_ALIGN(hnd->width, 16); + ycbcr->y = addr; + ycbcr->cb = (unsigned char *)addr + ystride * hnd->height; + ycbcr->cr = (unsigned char *)addr + ystride * hnd->height + 1; + ycbcr->ystride = ystride; + ycbcr->cstride = cstride; + ycbcr->chroma_step = 2; + break; + case HAL_PIXEL_FORMAT_YV12: + ystride = hnd->width; + cstride = GRALLOC_ALIGN(ystride / 2, 16); + ycbcr->y = addr; + ycbcr->cr = (unsigned char *)addr + ystride * hnd->height; + ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + cstride * hnd->height / 2; + ycbcr->ystride = ystride; + ycbcr->cstride = cstride; + ycbcr->chroma_step = 1; + break; + default: + ALOGE("Can not lock buffer, invalid format: 0x%x", hnd->format); + return -EINVAL; + } + + return 0; +} + +int gralloc_gbm_need_convert_format(buffer_handle_t _handle) +{ + struct gralloc_handle_t *handle = gralloc_handle(_handle); + return handle->convert_format; +} diff --git a/gralloc_gbm_proxy/gralloc_gbm_priv.h b/gralloc_gbm_proxy/gralloc_gbm_priv.h new file mode 100755 index 0000000..3d996af --- /dev/null +++ b/gralloc_gbm_proxy/gralloc_gbm_priv.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010-2011 Chia-I Wu + * Copyright (C) 2010-2011 LunarG Inc. + * Copyright (C) 2016 Linaro, Ltd., Rob Herring + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _GRALLOC_GBM_PRIV_H_ +#define _GRALLOC_GBM_PRIV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct gbm_device; +struct gbm_bo; + +int gralloc_gbm_handle_register(buffer_handle_t handle, struct gbm_device *gbm); +int gralloc_gbm_handle_unregister(buffer_handle_t handle); + +buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm, + int width, int height, int format, int usage, int *stride); +void gbm_free(buffer_handle_t handle); + +struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle); +buffer_handle_t gralloc_gbm_bo_get_handle(struct gbm_bo *bo); +int gralloc_gbm_get_gem_handle(buffer_handle_t handle); + +int gralloc_gbm_bo_lock(buffer_handle_t handle, int usage, int x, int y, int w, int h, void **addr); +int gralloc_gbm_bo_unlock(buffer_handle_t handle); +int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle, int usage, + int x, int y, int w, int h, struct android_ycbcr *ycbcr); +int gralloc_gbm_need_convert_format(buffer_handle_t _handle); + +struct gbm_device *gbm_dev_create(void); +void gbm_dev_destroy(struct gbm_device *gbm); + +#ifdef __cplusplus +} +#endif +#endif /* _GRALLOC_GBM_PRIV_H_ */ diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h index 94dd038..184b8e2 100644 --- a/include/EGL/eglext.h +++ b/include/EGL/eglext.h @@ -466,7 +466,7 @@ EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobF #define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004 typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC) (const EGLint *attrib_list); #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID (const EGLint *attrib_list); +// EGLAPI EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID (const EGLint *attrib_list); #endif #endif /* EGL_ANDROID_create_native_client_buffer */ @@ -517,7 +517,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglGetFrameTimestampsANDROID (EGLDisplay dpy, EGLS struct AHardwareBuffer; typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC) (const struct AHardwareBuffer *buffer); #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLClientBuffer EGLAPIENTRY eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer); +// EGLAPI EGLClientBuffer EGLAPIENTRY eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer); #endif #endif /* EGL_ANDROID_get_native_client_buffer */ diff --git a/util/u_gralloc/u_gralloc_libdrm.c b/util/u_gralloc/u_gralloc_libdrm.c index b250f4a..94c9f7f 100644 --- a/util/u_gralloc/u_gralloc_libdrm.c +++ b/util/u_gralloc/u_gralloc_libdrm.c @@ -29,6 +29,7 @@ struct libdrm_gralloc { }; static const char gbm_gralloc_module_name[] = "GBM Memory Allocator"; +static const char minigbm_gralloc_module_name[] = "CrOS Gralloc"; static int get_buffer_info(struct u_gralloc *gralloc, struct u_gralloc_buffer_handle *hnd, @@ -75,7 +76,8 @@ struct u_gralloc *u_gralloc_libdrm_create() { if (err) goto fail; - if (strcmp(gr->gralloc_module->common.name, gbm_gralloc_module_name) != 0) + if (strcmp(gr->gralloc_module->common.name, gbm_gralloc_module_name) != 0 + && strcmp(gr->gralloc_module->common.name, minigbm_gralloc_module_name) != 0) goto fail; gr->base.ops.get_buffer_basic_info = get_buffer_info;