diff options
Diffstat (limited to 'libs/ui/BlitHardware.cpp')
-rw-r--r-- | libs/ui/BlitHardware.cpp | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/libs/ui/BlitHardware.cpp b/libs/ui/BlitHardware.cpp new file mode 100644 index 0000000..90838b4 --- /dev/null +++ b/libs/ui/BlitHardware.cpp @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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 "SurfaceFlinger" + +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/mman.h> + +#include <cutils/log.h> + +#include <utils/Errors.h> + +#if HAVE_ANDROID_OS +#include <linux/fb.h> +#include <linux/msm_mdp.h> +#endif + +#include <ui/BlitHardware.h> + +/******************************************************************************/ + +namespace android { +class CopybitMSM7K : public copybit_t { +public: + CopybitMSM7K(); + ~CopybitMSM7K(); + + status_t getStatus() const { + if (mFD<0) return mFD; + return NO_ERROR; + } + + status_t setParameter(int name, int value); + + status_t get(int name); + + status_t blit( + const copybit_image_t& dst, + const copybit_image_t& src, + copybit_region_t const* region); + + status_t stretch( + const copybit_image_t& dst, + const copybit_image_t& src, + const copybit_rect_t& dst_rect, + const copybit_rect_t& src_rect, + copybit_region_t const* region); + +#if HAVE_ANDROID_OS +private: + static int copybit_set_parameter(copybit_t* handle, int name, int value); + static int copybit_blit( copybit_t* handle, + copybit_image_t const* dst, copybit_image_t const* src, + copybit_region_t const* region); + static int copybit_stretch(copybit_t* handle, + copybit_image_t const* dst, copybit_image_t const* src, + copybit_rect_t const* dst_rect, copybit_rect_t const* src_rect, + copybit_region_t const* region); + static int copybit_get(copybit_t* handle, int name); + + int getFormat(int format); + void setImage(mdp_img* img, const copybit_image_t& rhs); + void setRects(mdp_blit_req* req, const copybit_rect_t& dst, + const copybit_rect_t& src, const copybit_rect_t& scissor); + void setInfos(mdp_blit_req* req); + static void intersect(copybit_rect_t* out, + const copybit_rect_t& lhs, const copybit_rect_t& rhs); + status_t msm_copybit(void const* list); +#endif + int mFD; + uint8_t mAlpha; + uint8_t mFlags; +}; +}; // namespace android + +using namespace android; + +/******************************************************************************/ + +struct copybit_t* copybit_init() +{ + CopybitMSM7K* engine = new CopybitMSM7K(); + if (engine->getStatus() != NO_ERROR) { + delete engine; + engine = 0; + } + return (struct copybit_t*)engine; + +} + +int copybit_term(copybit_t* handle) +{ + delete static_cast<CopybitMSM7K*>(handle); + return NO_ERROR; +} + +namespace android { +/******************************************************************************/ + +static inline +int min(int a, int b) { + return (a<b) ? a : b; +} + +static inline +int max(int a, int b) { + return (a>b) ? a : b; +} + +static inline +void MULDIV(uint32_t& a, uint32_t& b, int mul, int div) +{ + if (mul != div) { + a = (mul * a) / div; + b = (mul * b) / div; + } +} + +//----------------------------------------------------------------------------- + +#if HAVE_ANDROID_OS + +int CopybitMSM7K::copybit_set_parameter(copybit_t* handle, int name, int value) +{ + return static_cast<CopybitMSM7K*>(handle)->setParameter(name, value); +} + +int CopybitMSM7K::copybit_get(copybit_t* handle, int name) +{ + return static_cast<CopybitMSM7K*>(handle)->get(name); +} + +int CopybitMSM7K::copybit_blit( + copybit_t* handle, + copybit_image_t const* dst, + copybit_image_t const* src, + struct copybit_region_t const* region) +{ + return static_cast<CopybitMSM7K*>(handle)->blit(*dst, *src, region); +} + +int CopybitMSM7K::copybit_stretch( + copybit_t* handle, + copybit_image_t const* dst, + copybit_image_t const* src, + copybit_rect_t const* dst_rect, + copybit_rect_t const* src_rect, + struct copybit_region_t const* region) +{ + return static_cast<CopybitMSM7K*>(handle)->stretch( + *dst, *src, *dst_rect, *src_rect, region); +} + +//----------------------------------------------------------------------------- + +CopybitMSM7K::CopybitMSM7K() + : mFD(-1), mAlpha(MDP_ALPHA_NOP), mFlags(0) +{ + int fd = open("/dev/graphics/fb0", O_RDWR, 0); + if (fd > 0) { + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == 0) { + if (!strcmp(finfo.id, "msmfb")) { + mFD = fd; + copybit_t::set_parameter = copybit_set_parameter; + copybit_t::get = copybit_get; + copybit_t::blit = copybit_blit; + copybit_t::stretch = copybit_stretch; + } + } + } + if (fd<0 || mFD<0) { + if (fd>0) { close(fd); } + mFD = -errno; + } +} + +CopybitMSM7K::~CopybitMSM7K() +{ + if (mFD > 0){ + close(mFD); + } +} + +status_t CopybitMSM7K::setParameter(int name, int value) +{ + switch(name) { + case COPYBIT_ROTATION_DEG: + switch (value) { + case 0: + mFlags &= ~0x7; + break; + case 90: + mFlags &= ~0x7; + mFlags |= MDP_ROT_90; + break; + case 180: + mFlags &= ~0x7; + mFlags |= MDP_ROT_180; + break; + case 270: + mFlags &= ~0x7; + mFlags |= MDP_ROT_270; + break; + default: + return BAD_VALUE; + } + break; + case COPYBIT_PLANE_ALPHA: + if (value < 0) value = 0; + if (value >= 256) value = 255; + mAlpha = value; + break; + case COPYBIT_DITHER: + if (value == COPYBIT_ENABLE) { + mFlags |= MDP_DITHER; + } else if (value == COPYBIT_DISABLE) { + mFlags &= ~MDP_DITHER; + } + break; + case COPYBIT_TRANSFORM: + mFlags &= ~0x7; + mFlags |= value & 0x7; + break; + default: + return BAD_VALUE; + } + return NO_ERROR; +} + +status_t CopybitMSM7K::get(int name) +{ + switch(name) { + case COPYBIT_MINIFICATION_LIMIT: + return 4; + case COPYBIT_MAGNIFICATION_LIMIT: + return 4; + case COPYBIT_SCALING_FRAC_BITS: + return 32; + case COPYBIT_ROTATION_STEP_DEG: + return 90; + } + return BAD_VALUE; +} + +status_t CopybitMSM7K::blit( + const copybit_image_t& dst, + const copybit_image_t& src, + copybit_region_t const* region) +{ + + copybit_rect_t dr = { 0, 0, dst.w, dst.h }; + copybit_rect_t sr = { 0, 0, src.w, src.h }; + return CopybitMSM7K::stretch(dst, src, dr, sr, region); +} + +status_t CopybitMSM7K::stretch( + const copybit_image_t& dst, + const copybit_image_t& src, + const copybit_rect_t& dst_rect, + const copybit_rect_t& src_rect, + copybit_region_t const* region) +{ + struct { + uint32_t count; + struct mdp_blit_req req[12]; + } list; + + if (mAlpha<255) { + switch (src.format) { + // we dont' support plane alpha with RGBA formats + case COPYBIT_RGBA_8888: + case COPYBIT_RGBA_5551: + case COPYBIT_RGBA_4444: + return INVALID_OPERATION; + } + } + + const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]); + const copybit_rect_t bounds = { 0, 0, dst.w, dst.h }; + copybit_rect_t clip; + list.count = 0; + int err = 0; + while (!err && region->next(region, &clip)) { + intersect(&clip, bounds, clip); + setInfos(&list.req[list.count]); + setImage(&list.req[list.count].dst, dst); + setImage(&list.req[list.count].src, src); + setRects(&list.req[list.count], dst_rect, src_rect, clip); + if (++list.count == maxCount) { + err = msm_copybit(&list); + list.count = 0; + } + } + if (!err && list.count) { + err = msm_copybit(&list); + } + return err; +} + +status_t CopybitMSM7K::msm_copybit(void const* list) +{ + int err = ioctl(mFD, MSMFB_BLIT, static_cast<mdp_blit_req_list const*>(list)); + LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno)); + if (err == 0) + return NO_ERROR; + return -errno; +} + +int CopybitMSM7K::getFormat(int format) +{ + switch (format) { + case COPYBIT_RGBA_8888: return MDP_RGBA_8888; + case COPYBIT_RGB_565: return MDP_RGB_565; + case COPYBIT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; + case COPYBIT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2; + } + return -1; +} + +void CopybitMSM7K::setInfos(mdp_blit_req* req) +{ + req->alpha = mAlpha; + req->transp_mask = MDP_TRANSP_NOP; + req->flags = mFlags; +} + +void CopybitMSM7K::setImage(mdp_img* img, const copybit_image_t& rhs) +{ + img->width = rhs.w; + img->height = rhs.h; + img->format = getFormat(rhs.format); + img->offset = rhs.offset; + img->memory_id = rhs.fd; +} + +void CopybitMSM7K::setRects(mdp_blit_req* e, + const copybit_rect_t& dst, const copybit_rect_t& src, + const copybit_rect_t& scissor) +{ + copybit_rect_t clip; + intersect(&clip, scissor, dst); + + e->dst_rect.x = clip.l; + e->dst_rect.y = clip.t; + e->dst_rect.w = clip.r - clip.l; + e->dst_rect.h = clip.b - clip.t; + + uint32_t W, H; + if (mFlags & COPYBIT_TRANSFORM_ROT_90) { + e->src_rect.x = (clip.t - dst.t) + src.t; + e->src_rect.y = (dst.r - clip.r) + src.l; + e->src_rect.w = (clip.b - clip.t); + e->src_rect.h = (clip.r - clip.l); + W = dst.b - dst.t; + H = dst.r - dst.l; + } else { + e->src_rect.x = (clip.l - dst.l) + src.l; + e->src_rect.y = (clip.t - dst.t) + src.t; + e->src_rect.w = (clip.r - clip.l); + e->src_rect.h = (clip.b - clip.t); + W = dst.r - dst.l; + H = dst.b - dst.t; + } + 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 (mFlags & COPYBIT_TRANSFORM_FLIP_V) { + e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + } + if (mFlags & COPYBIT_TRANSFORM_FLIP_H) { + e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w); + } +} + +void CopybitMSM7K::intersect(copybit_rect_t* out, + const copybit_rect_t& lhs, const copybit_rect_t& rhs) +{ + out->l = max(lhs.l, rhs.l); + out->t = max(lhs.t, rhs.t); + out->r = min(lhs.r, rhs.r); + out->b = min(lhs.b, rhs.b); +} + +/******************************************************************************/ +#else // HAVE_ANDROID_OS + +CopybitMSM7K::CopybitMSM7K() + : mFD(-1) +{ +} + +CopybitMSM7K::~CopybitMSM7K() +{ +} + +status_t CopybitMSM7K::setParameter(int name, int value) +{ + return NO_INIT; +} + +status_t CopybitMSM7K::get(int name) +{ + return BAD_VALUE; +} + +status_t CopybitMSM7K::blit( + const copybit_image_t& dst, + const copybit_image_t& src, + copybit_region_t const* region) +{ + return NO_INIT; +} + +status_t CopybitMSM7K::stretch( + const copybit_image_t& dst, + const copybit_image_t& src, + const copybit_rect_t& dst_rect, + const copybit_rect_t& src_rect, + copybit_region_t const* region) +{ + return NO_INIT; +} + +#endif // HAVE_ANDROID_OS + +/******************************************************************************/ +}; // namespace android |