merge from eclair
This commit is contained in:
		| @@ -1,35 +0,0 @@ | ||||
| BUILD_LIBCAMERA:= | ||||
| ifeq ($(BUILD_LIBCAMERA),true) | ||||
|  | ||||
| # When zero we link against libmmcamera; when 1, we dlopen libmmcamera. | ||||
| DLOPEN_LIBMMCAMERA:=1 | ||||
|  | ||||
| ifneq ($(BUILD_TINY_ANDROID),true) | ||||
|  | ||||
| LOCAL_PATH:= $(call my-dir) | ||||
|  | ||||
| include $(CLEAR_VARS) | ||||
|  | ||||
| LOCAL_SRC_FILES:= QualcommCameraHardware.cpp | ||||
|  | ||||
| LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA) | ||||
|  | ||||
| LOCAL_C_INCLUDES+= \ | ||||
| 	vendor/qcom/proprietary/mm-camera/common \ | ||||
| 	vendor/qcom/proprietary/mm-camera/apps/appslib \ | ||||
| 	vendor/qcom/proprietary/mm-camera/jpeg \ | ||||
| 	vendor/qcom/proprietary/mm-camera/jpeg/inc | ||||
|  | ||||
| LOCAL_SHARED_LIBRARIES:= libutils libui liblog | ||||
|  | ||||
| ifneq ($(DLOPEN_LIBMMCAMERA),1) | ||||
| LOCAL_SHARED_LIBRARIES+= libqcamera | ||||
| else | ||||
| LOCAL_SHARED_LIBRARIES+= libdl | ||||
| endif | ||||
|  | ||||
| LOCAL_MODULE:= libcamera | ||||
| include $(BUILD_SHARED_LIBRARY) | ||||
|  | ||||
| endif # BUILD_TINY_ANDROID | ||||
| endif # BUILD_LIBCAMERA | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,241 +0,0 @@ | ||||
| /* | ||||
| ** Copyright 2008, Google Inc. | ||||
| ** | ||||
| ** 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. | ||||
| */ | ||||
|  | ||||
| #ifndef ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H | ||||
| #define ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H | ||||
|  | ||||
| #include <ui/CameraHardwareInterface.h> | ||||
| #include <utils/MemoryBase.h> | ||||
| #include <utils/MemoryHeapBase.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| extern "C" { | ||||
| #include <linux/android_pmem.h> | ||||
| #include <media/msm_camera.h> | ||||
| #include <camera.h> | ||||
| } | ||||
|  | ||||
| struct str_map { | ||||
|     const char *const desc; | ||||
|     int val; | ||||
| }; | ||||
|  | ||||
| namespace android { | ||||
|  | ||||
| class QualcommCameraHardware : public CameraHardwareInterface { | ||||
| public: | ||||
|  | ||||
|     virtual sp<IMemoryHeap> getPreviewHeap() const; | ||||
|     virtual sp<IMemoryHeap> getRawHeap() const; | ||||
|  | ||||
|     virtual status_t dump(int fd, const Vector<String16>& args) const; | ||||
|     virtual status_t startPreview(preview_callback cb, void* user); | ||||
|     virtual void stopPreview(); | ||||
|     virtual bool previewEnabled(); | ||||
|     virtual status_t startRecording(recording_callback cb, void* user); | ||||
|     virtual void stopRecording(); | ||||
|     virtual bool recordingEnabled(); | ||||
|     virtual void releaseRecordingFrame(const sp<IMemory>& mem); | ||||
|     virtual status_t autoFocus(autofocus_callback, void *user); | ||||
|     virtual status_t takePicture(shutter_callback, raw_callback, | ||||
|                                  jpeg_callback, void *); | ||||
|     virtual status_t cancelPicture(bool cancel_shutter, | ||||
|                                    bool cancel_raw, bool cancel_jpeg); | ||||
|     virtual status_t setParameters(const CameraParameters& params); | ||||
|     virtual CameraParameters getParameters() const; | ||||
|     virtual void release(); | ||||
|  | ||||
|     static sp<CameraHardwareInterface> createInstance(); | ||||
|     static sp<QualcommCameraHardware> getInstance(); | ||||
|  | ||||
|     void receivePreviewFrame(struct msm_frame *frame); | ||||
|     void receiveJpegPicture(void); | ||||
|     void jpeg_set_location(); | ||||
|     void receiveJpegPictureFragment(uint8_t *buf, uint32_t size); | ||||
|     void notifyShutter(); | ||||
|  | ||||
| private: | ||||
|     QualcommCameraHardware(); | ||||
|     virtual ~QualcommCameraHardware(); | ||||
|     status_t startPreviewInternal(); | ||||
|     void stopPreviewInternal(); | ||||
|     friend void *auto_focus_thread(void *user); | ||||
|     void runAutoFocus(); | ||||
|     void cancelAutoFocus(); | ||||
|     bool native_set_dimension (int camfd); | ||||
|     bool native_jpeg_encode (void); | ||||
|     bool native_set_parm(cam_ctrl_type type, uint16_t length, void *value); | ||||
|     bool native_set_dimension(cam_ctrl_dimension_t *value); | ||||
|     int getParm(const char *parm_str, const str_map *parm_map); | ||||
|  | ||||
|     static wp<QualcommCameraHardware> singleton; | ||||
|  | ||||
|     /* These constants reflect the number of buffers that libmmcamera requires | ||||
|        for preview and raw, and need to be updated when libmmcamera | ||||
|        changes. | ||||
|     */ | ||||
|     static const int kPreviewBufferCount = 4; | ||||
|     static const int kRawBufferCount = 1; | ||||
|     static const int kJpegBufferCount = 1; | ||||
|  | ||||
|     //TODO: put the picture dimensions in the CameraParameters object; | ||||
|     CameraParameters mParameters; | ||||
|     int mPreviewHeight; | ||||
|     int mPreviewWidth; | ||||
|     int mRawHeight; | ||||
|     int mRawWidth; | ||||
|     unsigned int frame_size; | ||||
|     bool mCameraRunning; | ||||
|     bool mPreviewInitialized; | ||||
|  | ||||
|     // This class represents a heap which maintains several contiguous | ||||
|     // buffers.  The heap may be backed by pmem (when pmem_pool contains | ||||
|     // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL). | ||||
|  | ||||
|     struct MemPool : public RefBase { | ||||
|         MemPool(int buffer_size, int num_buffers, | ||||
|                 int frame_size, | ||||
|                 int frame_offset, | ||||
|                 const char *name); | ||||
|  | ||||
|         virtual ~MemPool() = 0; | ||||
|  | ||||
|         void completeInitialization(); | ||||
|         bool initialized() const { | ||||
|             return mHeap != NULL && mHeap->base() != MAP_FAILED; | ||||
|         } | ||||
|  | ||||
|         virtual status_t dump(int fd, const Vector<String16>& args) const; | ||||
|  | ||||
|         int mBufferSize; | ||||
|         int mNumBuffers; | ||||
|         int mFrameSize; | ||||
|         int mFrameOffset; | ||||
|         sp<MemoryHeapBase> mHeap; | ||||
|         sp<MemoryBase> *mBuffers; | ||||
|  | ||||
|         const char *mName; | ||||
|     }; | ||||
|  | ||||
|     struct AshmemPool : public MemPool { | ||||
|         AshmemPool(int buffer_size, int num_buffers, | ||||
|                    int frame_size, | ||||
|                    int frame_offset, | ||||
|                    const char *name); | ||||
|     }; | ||||
|  | ||||
|     struct PmemPool : public MemPool { | ||||
|         PmemPool(const char *pmem_pool, | ||||
|                  int control_camera_fd, int pmem_type, | ||||
|                  int buffer_size, int num_buffers, | ||||
|                  int frame_size, int frame_offset, | ||||
|                  const char *name); | ||||
|         virtual ~PmemPool(); | ||||
|         int mFd; | ||||
|         int mPmemType; | ||||
|         int mCameraControlFd; | ||||
|         uint32_t mAlignedSize; | ||||
|         struct pmem_region mSize; | ||||
|     }; | ||||
|  | ||||
|     sp<PmemPool> mPreviewHeap; | ||||
|     sp<PmemPool> mThumbnailHeap; | ||||
|     sp<PmemPool> mRawHeap; | ||||
|     sp<AshmemPool> mJpegHeap; | ||||
|  | ||||
|     void startCamera(); | ||||
|     bool initPreview(); | ||||
|     void deinitPreview(); | ||||
|     bool initRaw(bool initJpegHeap); | ||||
|     void deinitRaw(); | ||||
|  | ||||
|     bool mFrameThreadRunning; | ||||
|     Mutex mFrameThreadWaitLock; | ||||
|     Condition mFrameThreadWait; | ||||
|     friend void *frame_thread(void *user); | ||||
|     void runFrameThread(void *data); | ||||
|  | ||||
|     bool mShutterPending; | ||||
|     Mutex mShutterLock; | ||||
|  | ||||
|     bool mSnapshotThreadRunning; | ||||
|     Mutex mSnapshotThreadWaitLock; | ||||
|     Condition mSnapshotThreadWait; | ||||
|     friend void *snapshot_thread(void *user); | ||||
|     void runSnapshotThread(void *data); | ||||
|  | ||||
|     void initDefaultParameters(); | ||||
|  | ||||
|     void setAntibanding(); | ||||
|     void setEffect(); | ||||
|     void setWhiteBalance(); | ||||
|  | ||||
|     Mutex mLock; | ||||
|     bool mReleasedRecordingFrame; | ||||
|  | ||||
|     void receiveRawPicture(void); | ||||
|  | ||||
|     Mutex mCallbackLock; | ||||
| 	Mutex mRecordLock; | ||||
| 	Mutex mRecordFrameLock; | ||||
| 	Condition mRecordWait; | ||||
|     Condition mStateWait; | ||||
|  | ||||
|     /* mJpegSize keeps track of the size of the accumulated JPEG.  We clear it | ||||
|        when we are about to take a picture, so at any time it contains either | ||||
|        zero, or the size of the last JPEG picture taken. | ||||
|     */ | ||||
|     uint32_t mJpegSize; | ||||
|  | ||||
|     shutter_callback    mShutterCallback; | ||||
|     raw_callback        mRawPictureCallback; | ||||
|     jpeg_callback       mJpegPictureCallback; | ||||
|     void                *mPictureCallbackCookie; | ||||
|  | ||||
|     autofocus_callback  mAutoFocusCallback; | ||||
|     void                *mAutoFocusCallbackCookie; | ||||
|  | ||||
|     preview_callback    mPreviewCallback; | ||||
|     void                *mPreviewCallbackCookie; | ||||
|     recording_callback  mRecordingCallback; | ||||
|     void                *mRecordingCallbackCookie; | ||||
|     unsigned int        mPreviewFrameSize; | ||||
|     int                 mRawSize; | ||||
|     int                 mJpegMaxSize; | ||||
|  | ||||
| #if DLOPEN_LIBMMCAMERA | ||||
|     void *libmmcamera; | ||||
| #endif | ||||
|  | ||||
|     int mCameraControlFd; | ||||
|     cam_ctrl_dimension_t mDimension; | ||||
|     bool mAutoFocusThreadRunning; | ||||
|     Mutex mAutoFocusThreadLock; | ||||
|     int mAutoFocusFd; | ||||
|  | ||||
|     pthread_t mCamConfigThread; | ||||
|     pthread_t mFrameThread; | ||||
|     pthread_t mSnapshotThread; | ||||
|  | ||||
|     common_crop_t mCrop; | ||||
|  | ||||
|     struct msm_frame frames[kPreviewBufferCount]; | ||||
|     bool mInPreviewCallback; | ||||
| }; | ||||
|  | ||||
| }; // namespace android | ||||
|  | ||||
| #endif | ||||
| @@ -16,10 +16,27 @@ | ||||
| LOCAL_PATH:= $(call my-dir) | ||||
| # HAL module implemenation, not prelinked and stored in | ||||
| # hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so | ||||
|  | ||||
| ifeq ($(TARGET_BOARD_PLATFORM),msm7k) | ||||
| include $(CLEAR_VARS) | ||||
| LOCAL_PRELINK_MODULE := false | ||||
| LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw | ||||
| LOCAL_SHARED_LIBRARIES := liblog | ||||
| LOCAL_SRC_FILES := copybit.c | ||||
| LOCAL_SRC_FILES := copybit.cpp | ||||
| LOCAL_MODULE := copybit.msm7k | ||||
| LOCAL_C_INCLUDES += hardware/msm7k/libgralloc | ||||
| LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1 | ||||
| include $(BUILD_SHARED_LIBRARY) | ||||
| endif | ||||
|  | ||||
| ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) | ||||
| include $(CLEAR_VARS) | ||||
| LOCAL_PRELINK_MODULE := false | ||||
| LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw | ||||
| LOCAL_SHARED_LIBRARIES := liblog | ||||
| LOCAL_SRC_FILES := copybit.cpp | ||||
| LOCAL_MODULE := copybit.qsd8k | ||||
| LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc | ||||
| LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 | ||||
| include $(BUILD_SHARED_LIBRARY) | ||||
| endif | ||||
|   | ||||
| @@ -34,6 +34,20 @@ | ||||
| 
 | ||||
| #include <hardware/copybit.h> | ||||
| 
 | ||||
| #include "gralloc_priv.h" | ||||
| 
 | ||||
| #define DEBUG_MDP_ERRORS 1 | ||||
| 
 | ||||
| /******************************************************************************/ | ||||
| 
 | ||||
| #if defined(COPYBIT_MSM7K) | ||||
| #define MAX_SCALE_FACTOR    (4) | ||||
| #elif defined(COPYBIT_QSD8K) | ||||
| #define MAX_SCALE_FACTOR    (8) | ||||
| #else | ||||
| #error "Unsupported MDP version" | ||||
| #endif | ||||
| 
 | ||||
| /******************************************************************************/ | ||||
| 
 | ||||
| /** State information for each device instance */ | ||||
| @@ -52,21 +66,21 @@ static int open_copybit(const struct hw_module_t* module, const char* name, | ||||
|         struct hw_device_t** device); | ||||
| 
 | ||||
| static struct hw_module_methods_t copybit_module_methods = { | ||||
|     .open =  open_copybit | ||||
|     open:  open_copybit | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * The COPYBIT Module | ||||
|  */ | ||||
| const struct copybit_module_t HAL_MODULE_INFO_SYM = { | ||||
|     .common = { | ||||
|         .tag = HARDWARE_MODULE_TAG, | ||||
|         .version_major = 1, | ||||
|         .version_minor = 0, | ||||
|         .id = COPYBIT_HARDWARE_MODULE_ID, | ||||
|         .name = "QCT MSM7K COPYBIT Module", | ||||
|         .author = "Google, Inc.", | ||||
|         .methods = ©bit_module_methods, | ||||
| struct copybit_module_t HAL_MODULE_INFO_SYM = { | ||||
|     common: { | ||||
|         tag: HARDWARE_MODULE_TAG, | ||||
|         version_major: 1, | ||||
|         version_minor: 0, | ||||
|         id: COPYBIT_HARDWARE_MODULE_ID, | ||||
|         name: "QCT MSM7K COPYBIT Module", | ||||
|         author: "Google, Inc.", | ||||
|         methods: ©bit_module_methods | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| @@ -103,9 +117,11 @@ static void intersect(struct copybit_rect_t *out, | ||||
| /** convert COPYBIT_FORMAT to MDP format */ | ||||
| static int get_format(int format) { | ||||
|     switch (format) { | ||||
|     case COPYBIT_FORMAT_RGB_565:       return MDP_RGB_565; | ||||
|     case COPYBIT_FORMAT_RGBX_8888:     return MDP_RGBX_8888; | ||||
|     case COPYBIT_FORMAT_RGB_888:       return MDP_RGB_888; | ||||
|     case COPYBIT_FORMAT_RGBA_8888:     return MDP_RGBA_8888; | ||||
|     case COPYBIT_FORMAT_BGRA_8888:     return MDP_BGRA_8888; | ||||
|     case COPYBIT_FORMAT_RGB_565:       return MDP_RGB_565; | ||||
|     case COPYBIT_FORMAT_YCbCr_422_SP:  return MDP_Y_CBCR_H2V1; | ||||
|     case COPYBIT_FORMAT_YCbCr_420_SP:  return MDP_Y_CBCR_H2V2; | ||||
|     } | ||||
| @@ -113,15 +129,27 @@ static int get_format(int format) { | ||||
| } | ||||
| 
 | ||||
| /** convert from copybit image to mdp image structure */ | ||||
| static void set_image(struct mdp_img *img, | ||||
|                       const struct copybit_image_t *rhs) { | ||||
| static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs)  | ||||
| { | ||||
|     private_handle_t* hnd = (private_handle_t*)rhs->handle; | ||||
|     img->width      = rhs->w; | ||||
|     img->height     = rhs->h; | ||||
|     img->format     = get_format(rhs->format); | ||||
|     img->offset     = rhs->offset; | ||||
|     img->memory_id  = rhs->fd; | ||||
|     img->offset     = hnd->offset; | ||||
| #if defined(COPYBIT_MSM7K) | ||||
|     if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { | ||||
|         img->memory_id = hnd->gpu_fd; | ||||
|         if (img->format == MDP_RGBA_8888) { | ||||
|             // msm7201A GPU only supports BGRA_8888 destinations
 | ||||
|             img->format = MDP_BGRA_8888; | ||||
|         } | ||||
|     } else { | ||||
|         img->memory_id = hnd->fd; | ||||
|     } | ||||
| #else | ||||
|     img->memory_id  = hnd->fd; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /** setup rectangles */ | ||||
| static void set_rects(struct copybit_context_t *dev, | ||||
|                       struct mdp_blit_req *e, | ||||
| @@ -166,7 +194,7 @@ static void set_rects(struct copybit_context_t *dev, | ||||
| static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) { | ||||
|     req->alpha = dev->mAlpha; | ||||
|     req->transp_mask = MDP_TRANSP_NOP; | ||||
|     req->flags = dev->mFlags; | ||||
|     req->flags = dev->mFlags | MDP_BLEND_FG_PREMULT; | ||||
| } | ||||
| 
 | ||||
| /** copy the bits */ | ||||
| @@ -175,10 +203,37 @@ static int msm_copybit(struct copybit_context_t *dev, void const *list) | ||||
|     int err = ioctl(dev->mFD, MSMFB_BLIT, | ||||
|                     (struct mdp_blit_req_list const*)list); | ||||
|     LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno)); | ||||
|     if (err == 0) | ||||
|     if (err == 0) { | ||||
|         return 0; | ||||
|     else | ||||
|     } else { | ||||
| #if DEBUG_MDP_ERRORS | ||||
|         struct mdp_blit_req_list const* l = (struct mdp_blit_req_list const*)list; | ||||
|         for (int i=0 ; i<l->count ; i++) { | ||||
|             LOGD("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n" | ||||
|                  "    dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n" | ||||
|                  "    flags=%08lx" | ||||
|                     , | ||||
|                     i, | ||||
|                     l->req[i].src.width, | ||||
|                     l->req[i].src.height, | ||||
|                     l->req[i].src.format, | ||||
|                     l->req[i].src_rect.x, | ||||
|                     l->req[i].src_rect.y, | ||||
|                     l->req[i].src_rect.w, | ||||
|                     l->req[i].src_rect.h, | ||||
|                     l->req[i].dst.width, | ||||
|                     l->req[i].dst.height, | ||||
|                     l->req[i].dst.format, | ||||
|                     l->req[i].dst_rect.x, | ||||
|                     l->req[i].dst_rect.y, | ||||
|                     l->req[i].dst_rect.w, | ||||
|                     l->req[i].dst_rect.h, | ||||
|                     l->req[i].flags | ||||
|             ); | ||||
|         } | ||||
| #endif | ||||
|         return -errno; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*****************************************************************************/ | ||||
| @@ -257,10 +312,10 @@ static int get(struct copybit_device_t *dev, int name) | ||||
|     if (ctx) { | ||||
|         switch(name) { | ||||
|         case COPYBIT_MINIFICATION_LIMIT: | ||||
|             value = 4; | ||||
|             value = MAX_SCALE_FACTOR; | ||||
|             break; | ||||
|         case COPYBIT_MAGNIFICATION_LIMIT: | ||||
|             value = 4; | ||||
|             value = MAX_SCALE_FACTOR; | ||||
|             break; | ||||
|         case COPYBIT_SCALING_FRAC_BITS: | ||||
|             value = 32; | ||||
| @@ -304,7 +359,13 @@ static int stretch_copybit( | ||||
|                     return -EINVAL; | ||||
|             } | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         if (src_rect->l < 0 || src_rect->r > src->w || | ||||
|             src_rect->t < 0 || src_rect->b > src->h) { | ||||
|             // this is always invalid
 | ||||
|             return -EINVAL; | ||||
|         } | ||||
| 
 | ||||
|         const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]); | ||||
|         const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h }; | ||||
|         struct copybit_rect_t clip; | ||||
| @@ -312,10 +373,18 @@ static int stretch_copybit( | ||||
|         status = 0; | ||||
|         while ((status == 0) && region->next(region, &clip)) { | ||||
|             intersect(&clip, &bounds, &clip); | ||||
|             set_infos(ctx, &list.req[list.count]); | ||||
|             set_image(&list.req[list.count].dst, dst); | ||||
|             set_image(&list.req[list.count].src, src); | ||||
|             set_rects(ctx, &list.req[list.count], dst_rect, src_rect, &clip); | ||||
|             mdp_blit_req* req = &list.req[list.count]; | ||||
|             set_infos(ctx, req); | ||||
|             set_image(&req->dst, dst); | ||||
|             set_image(&req->src, src); | ||||
|             set_rects(ctx, req, dst_rect, src_rect, &clip); | ||||
| 
 | ||||
|             if (req->src_rect.w<=0 || req->src_rect.h<=0) | ||||
|                 continue; | ||||
| 
 | ||||
|             if (req->dst_rect.w<=0 || req->dst_rect.h<=0) | ||||
|                 continue; | ||||
| 
 | ||||
|             if (++list.count == maxCount) { | ||||
|                 status = msm_copybit(ctx, &list); | ||||
|                 list.count = 0; | ||||
| @@ -360,12 +429,13 @@ static int open_copybit(const struct hw_module_t* module, const char* name, | ||||
|         struct hw_device_t** device) | ||||
| { | ||||
|     int status = -EINVAL; | ||||
|     struct copybit_context_t *ctx = malloc(sizeof(struct copybit_context_t)); | ||||
|     copybit_context_t *ctx; | ||||
|     ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t)); | ||||
|     memset(ctx, 0, sizeof(*ctx)); | ||||
| 
 | ||||
|     ctx->device.common.tag = HARDWARE_DEVICE_TAG; | ||||
|     ctx->device.common.version = 0; | ||||
|     ctx->device.common.module = module; | ||||
|     ctx->device.common.version = 1; | ||||
|     ctx->device.common.module = const_cast<hw_module_t*>(module); | ||||
|     ctx->device.common.close = close_copybit; | ||||
|     ctx->device.set_parameter = set_parameter_copybit; | ||||
|     ctx->device.get = get; | ||||
							
								
								
									
										32
									
								
								libgralloc-qsd8k/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								libgralloc-qsd8k/Android.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| # 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. | ||||
|  | ||||
| LOCAL_PATH := $(call my-dir) | ||||
|  | ||||
| # HAL module implemenation, not prelinked and stored in | ||||
| # hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so | ||||
| include $(CLEAR_VARS) | ||||
| LOCAL_PRELINK_MODULE := false | ||||
| LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw | ||||
| LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM | ||||
|  | ||||
| LOCAL_SRC_FILES := 	\ | ||||
| 	allocator.cpp 	\ | ||||
| 	gralloc.cpp 	\ | ||||
| 	framebuffer.cpp \ | ||||
| 	mapper.cpp | ||||
| 	 | ||||
| LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) | ||||
| LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" | ||||
| include $(BUILD_SHARED_LIBRARY) | ||||
							
								
								
									
										170
									
								
								libgralloc-qsd8k/allocator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								libgralloc-qsd8k/allocator.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| /* | ||||
|  * Copyright (C) 2009 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. | ||||
|  */ | ||||
|  | ||||
| #include <cutils/log.h> | ||||
|  | ||||
| #include "allocator.h" | ||||
|  | ||||
|  | ||||
| // align all the memory blocks on a cache-line boundary | ||||
| const int SimpleBestFitAllocator::kMemoryAlign = 32; | ||||
|  | ||||
| SimpleBestFitAllocator::SimpleBestFitAllocator() | ||||
|     : mHeapSize(0) | ||||
| { | ||||
| } | ||||
|  | ||||
| SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) | ||||
|     : mHeapSize(0) | ||||
| { | ||||
|     setSize(size); | ||||
| } | ||||
|  | ||||
| SimpleBestFitAllocator::~SimpleBestFitAllocator() | ||||
| { | ||||
|     while(!mList.isEmpty()) { | ||||
|         delete mList.remove(mList.head()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| ssize_t SimpleBestFitAllocator::setSize(size_t size) | ||||
| { | ||||
|     Locker::Autolock _l(mLock); | ||||
|     if (mHeapSize != 0) return -EINVAL; | ||||
|     size_t pagesize = getpagesize(); | ||||
|     mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); | ||||
|     chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); | ||||
|     mList.insertHead(node); | ||||
|     return size; | ||||
| } | ||||
|      | ||||
|      | ||||
| size_t SimpleBestFitAllocator::size() const | ||||
| { | ||||
|     return mHeapSize; | ||||
| } | ||||
|  | ||||
| ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) | ||||
| { | ||||
|     Locker::Autolock _l(mLock); | ||||
|     if (mHeapSize == 0) return -EINVAL; | ||||
|     ssize_t offset = alloc(size, flags); | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| ssize_t SimpleBestFitAllocator::deallocate(size_t offset) | ||||
| { | ||||
|     Locker::Autolock _l(mLock); | ||||
|     if (mHeapSize == 0) return -EINVAL; | ||||
|     chunk_t const * const freed = dealloc(offset); | ||||
|     if (freed) { | ||||
|         return 0; | ||||
|     } | ||||
|     return -ENOENT; | ||||
| } | ||||
|  | ||||
| ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) | ||||
| { | ||||
|     if (size == 0) { | ||||
|         return 0; | ||||
|     } | ||||
|     size = (size + kMemoryAlign-1) / kMemoryAlign; | ||||
|     chunk_t* free_chunk = 0; | ||||
|     chunk_t* cur = mList.head(); | ||||
|  | ||||
|     size_t pagesize = getpagesize(); | ||||
|     while (cur) { | ||||
|         int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; | ||||
|  | ||||
|         // best fit | ||||
|         if (cur->free && (cur->size >= (size+extra))) { | ||||
|             if ((!free_chunk) || (cur->size < free_chunk->size)) { | ||||
|                 free_chunk = cur; | ||||
|             } | ||||
|             if (cur->size == size) { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         cur = cur->next; | ||||
|     } | ||||
|  | ||||
|     if (free_chunk) { | ||||
|         const size_t free_size = free_chunk->size; | ||||
|         free_chunk->free = 0; | ||||
|         free_chunk->size = size; | ||||
|         if (free_size > size) { | ||||
|             int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; | ||||
|             if (extra) { | ||||
|                 chunk_t* split = new chunk_t(free_chunk->start, extra); | ||||
|                 free_chunk->start += extra; | ||||
|                 mList.insertBefore(free_chunk, split); | ||||
|             } | ||||
|  | ||||
|             LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)), | ||||
|                     "page is not aligned!!!"); | ||||
|  | ||||
|             const ssize_t tail_free = free_size - (size+extra); | ||||
|             if (tail_free > 0) { | ||||
|                 chunk_t* split = new chunk_t( | ||||
|                         free_chunk->start + free_chunk->size, tail_free); | ||||
|                 mList.insertAfter(free_chunk, split); | ||||
|             } | ||||
|         } | ||||
|         return (free_chunk->start)*kMemoryAlign; | ||||
|     } | ||||
|     return -ENOMEM; | ||||
| } | ||||
|  | ||||
| SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) | ||||
| { | ||||
|     start = start / kMemoryAlign; | ||||
|     chunk_t* cur = mList.head(); | ||||
|     while (cur) { | ||||
|         if (cur->start == start) { | ||||
|             LOG_FATAL_IF(cur->free, | ||||
|                 "block at offset 0x%08lX of size 0x%08lX already freed", | ||||
|                 cur->start*kMemoryAlign, cur->size*kMemoryAlign); | ||||
|  | ||||
|             // merge freed blocks together | ||||
|             chunk_t* freed = cur; | ||||
|             cur->free = 1; | ||||
|             do { | ||||
|                 chunk_t* const p = cur->prev; | ||||
|                 chunk_t* const n = cur->next; | ||||
|                 if (p && (p->free || !cur->size)) { | ||||
|                     freed = p; | ||||
|                     p->size += cur->size; | ||||
|                     mList.remove(cur); | ||||
|                     delete cur; | ||||
|                 } | ||||
|                 cur = n; | ||||
|             } while (cur && cur->free); | ||||
|  | ||||
|             #ifndef NDEBUG | ||||
|                 if (!freed->free) { | ||||
|                     dump_l("dealloc (!freed->free)"); | ||||
|                 } | ||||
|             #endif | ||||
|             LOG_FATAL_IF(!freed->free, | ||||
|                 "freed block at offset 0x%08lX of size 0x%08lX is not free!", | ||||
|                 freed->start * kMemoryAlign, freed->size * kMemoryAlign); | ||||
|  | ||||
|             return freed; | ||||
|         } | ||||
|         cur = cur->next; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										129
									
								
								libgralloc-qsd8k/allocator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								libgralloc-qsd8k/allocator.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /* | ||||
|  * Copyright (C) 2009 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. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef GRALLOC_ALLOCATOR_H_ | ||||
| #define GRALLOC_ALLOCATOR_H_ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include "gr.h" | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| /* | ||||
|  * A simple templatized doubly linked-list implementation | ||||
|  */ | ||||
|  | ||||
| template <typename NODE> | ||||
| class LinkedList | ||||
| { | ||||
|     NODE*  mFirst; | ||||
|     NODE*  mLast; | ||||
|  | ||||
| public: | ||||
|                 LinkedList() : mFirst(0), mLast(0) { } | ||||
|     bool        isEmpty() const { return mFirst == 0; } | ||||
|     NODE const* head() const { return mFirst; } | ||||
|     NODE*       head() { return mFirst; } | ||||
|     NODE const* tail() const { return mLast; } | ||||
|     NODE*       tail() { return mLast; } | ||||
|  | ||||
|     void insertAfter(NODE* node, NODE* newNode) { | ||||
|         newNode->prev = node; | ||||
|         newNode->next = node->next; | ||||
|         if (node->next == 0) mLast = newNode; | ||||
|         else                 node->next->prev = newNode; | ||||
|         node->next = newNode; | ||||
|     } | ||||
|  | ||||
|     void insertBefore(NODE* node, NODE* newNode) { | ||||
|          newNode->prev = node->prev; | ||||
|          newNode->next = node; | ||||
|          if (node->prev == 0)   mFirst = newNode; | ||||
|          else                   node->prev->next = newNode; | ||||
|          node->prev = newNode; | ||||
|     } | ||||
|  | ||||
|     void insertHead(NODE* newNode) { | ||||
|         if (mFirst == 0) { | ||||
|             mFirst = mLast = newNode; | ||||
|             newNode->prev = newNode->next = 0; | ||||
|         } else { | ||||
|             newNode->prev = 0; | ||||
|             newNode->next = mFirst; | ||||
|             mFirst->prev = newNode; | ||||
|             mFirst = newNode; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     void insertTail(NODE* newNode) { | ||||
|         if (mLast == 0) { | ||||
|             insertHead(newNode); | ||||
|         } else { | ||||
|             newNode->prev = mLast; | ||||
|             newNode->next = 0; | ||||
|             mLast->next = newNode; | ||||
|             mLast = newNode; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     NODE* remove(NODE* node) { | ||||
|         if (node->prev == 0)    mFirst = node->next; | ||||
|         else                    node->prev->next = node->next; | ||||
|         if (node->next == 0)    mLast = node->prev; | ||||
|         else                    node->next->prev = node->prev; | ||||
|         return node; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class SimpleBestFitAllocator | ||||
| { | ||||
| public: | ||||
|  | ||||
|     SimpleBestFitAllocator(); | ||||
|     SimpleBestFitAllocator(size_t size); | ||||
|     ~SimpleBestFitAllocator(); | ||||
|  | ||||
|     ssize_t     setSize(size_t size); | ||||
|  | ||||
|     ssize_t     allocate(size_t size, uint32_t flags = 0); | ||||
|     ssize_t     deallocate(size_t offset); | ||||
|     size_t      size() const; | ||||
|  | ||||
| private: | ||||
|     struct chunk_t { | ||||
|         chunk_t(size_t start, size_t size)  | ||||
|             : start(start), size(size), free(1), prev(0), next(0) { | ||||
|         } | ||||
|         size_t              start; | ||||
|         size_t              size : 28; | ||||
|         int                 free : 4; | ||||
|         mutable chunk_t*    prev; | ||||
|         mutable chunk_t*    next; | ||||
|     }; | ||||
|  | ||||
|     ssize_t  alloc(size_t size, uint32_t flags); | ||||
|     chunk_t* dealloc(size_t start); | ||||
|  | ||||
|     static const int    kMemoryAlign; | ||||
|     mutable Locker      mLock; | ||||
|     LinkedList<chunk_t> mList; | ||||
|     size_t              mHeapSize; | ||||
| }; | ||||
|  | ||||
| #endif /* GRALLOC_ALLOCATOR_H_ */ | ||||
							
								
								
									
										437
									
								
								libgralloc-qsd8k/framebuffer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										437
									
								
								libgralloc-qsd8k/framebuffer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,437 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #include <sys/mman.h> | ||||
|  | ||||
| #include <dlfcn.h> | ||||
|  | ||||
| #include <cutils/ashmem.h> | ||||
| #include <cutils/log.h> | ||||
|  | ||||
| #include <hardware/hardware.h> | ||||
| #include <hardware/gralloc.h> | ||||
|  | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <cutils/log.h> | ||||
| #include <cutils/atomic.h> | ||||
|  | ||||
| #include <linux/fb.h> | ||||
| #include <linux/msm_mdp.h> | ||||
|  | ||||
| #include <GLES/gl.h> | ||||
|  | ||||
| #include "gralloc_priv.h" | ||||
| #include "gr.h" | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| // numbers of buffers for page flipping | ||||
| #define NUM_BUFFERS 2 | ||||
|  | ||||
|  | ||||
| enum { | ||||
|     PAGE_FLIP = 0x00000001, | ||||
|     LOCKED = 0x00000002 | ||||
| }; | ||||
|  | ||||
| struct fb_context_t { | ||||
|     framebuffer_device_t  device; | ||||
| }; | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static void | ||||
| msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, | ||||
|                 int x, int y, int w, int h); | ||||
|  | ||||
| static int fb_setSwapInterval(struct framebuffer_device_t* dev, | ||||
|             int interval) | ||||
| { | ||||
|     fb_context_t* ctx = (fb_context_t*)dev; | ||||
|     if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) | ||||
|         return -EINVAL; | ||||
|     // FIXME: implement fb_setSwapInterval | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int fb_setUpdateRect(struct framebuffer_device_t* dev, | ||||
|         int l, int t, int w, int h) | ||||
| { | ||||
|     if (((w|h) <= 0) || ((l|t)<0)) | ||||
|         return -EINVAL; | ||||
|          | ||||
|     fb_context_t* ctx = (fb_context_t*)dev; | ||||
|     private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|             dev->common.module); | ||||
|     m->info.reserved[0] = 0x54445055; // "UPDT"; | ||||
|     m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); | ||||
|     m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) | ||||
| { | ||||
|     if (private_handle_t::validate(buffer) < 0) | ||||
|         return -EINVAL; | ||||
|  | ||||
|     fb_context_t* ctx = (fb_context_t*)dev; | ||||
|  | ||||
|     private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer); | ||||
|     private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|             dev->common.module); | ||||
|      | ||||
|     if (m->currentBuffer) { | ||||
|         m->base.unlock(&m->base, m->currentBuffer); | ||||
|         m->currentBuffer = 0; | ||||
|     } | ||||
|  | ||||
|     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { | ||||
|  | ||||
|         m->base.lock(&m->base, buffer,  | ||||
|                 private_module_t::PRIV_USAGE_LOCKED_FOR_POST,  | ||||
|                 0, 0, m->info.xres, m->info.yres, NULL); | ||||
|  | ||||
|         const size_t offset = hnd->base - m->framebuffer->base; | ||||
|         m->info.activate = FB_ACTIVATE_VBL; | ||||
|         m->info.yoffset = offset / m->finfo.line_length; | ||||
|         if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { | ||||
|             LOGE("FBIOPUT_VSCREENINFO failed"); | ||||
|             m->base.unlock(&m->base, buffer);  | ||||
|             return -errno; | ||||
|         } | ||||
|         m->currentBuffer = buffer; | ||||
|          | ||||
|     } else { | ||||
|         // If we can't do the page_flip, just copy the buffer to the front  | ||||
|         // FIXME: use copybit HAL instead of memcpy | ||||
|          | ||||
|         void* fb_vaddr; | ||||
|         void* buffer_vaddr; | ||||
|          | ||||
|         m->base.lock(&m->base, m->framebuffer,  | ||||
|                 GRALLOC_USAGE_SW_WRITE_RARELY,  | ||||
|                 0, 0, m->info.xres, m->info.yres, | ||||
|                 &fb_vaddr); | ||||
|  | ||||
|         m->base.lock(&m->base, buffer,  | ||||
|                 GRALLOC_USAGE_SW_READ_RARELY,  | ||||
|                 0, 0, m->info.xres, m->info.yres, | ||||
|                 &buffer_vaddr); | ||||
|  | ||||
|         //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); | ||||
|  | ||||
|         msm_copy_buffer(m->framebuffer, m->framebuffer->fd, | ||||
|                 m->info.xres, m->info.yres, | ||||
|                 m->info.xoffset, m->info.yoffset, | ||||
|                 m->info.width, m->info.height); | ||||
|  | ||||
|         m->base.unlock(&m->base, buffer);  | ||||
|         m->base.unlock(&m->base, m->framebuffer);  | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int fb_compositionComplete(struct framebuffer_device_t* dev) | ||||
| { | ||||
|     // STOPSHIP: Properly implement composition complete callback | ||||
|     glFinish(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| int mapFrameBufferLocked(struct private_module_t* module) | ||||
| { | ||||
|     // already initialized... | ||||
|     if (module->framebuffer) { | ||||
|         return 0; | ||||
|     } | ||||
|          | ||||
|     char const * const device_template[] = { | ||||
|             "/dev/graphics/fb%u", | ||||
|             "/dev/fb%u", | ||||
|             0 }; | ||||
|  | ||||
|     int fd = -1; | ||||
|     int i=0; | ||||
|     char name[64]; | ||||
|  | ||||
|     while ((fd==-1) && device_template[i]) { | ||||
|         snprintf(name, 64, device_template[i], 0); | ||||
|         fd = open(name, O_RDWR, 0); | ||||
|         i++; | ||||
|     } | ||||
|     if (fd < 0) | ||||
|         return -errno; | ||||
|  | ||||
|     struct fb_fix_screeninfo finfo; | ||||
|     if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) | ||||
|         return -errno; | ||||
|  | ||||
|     struct fb_var_screeninfo info; | ||||
|     if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) | ||||
|         return -errno; | ||||
|  | ||||
|     info.reserved[0] = 0; | ||||
|     info.reserved[1] = 0; | ||||
|     info.reserved[2] = 0; | ||||
|     info.xoffset = 0; | ||||
|     info.yoffset = 0; | ||||
|     info.activate = FB_ACTIVATE_NOW; | ||||
|  | ||||
|     /* | ||||
|      * Explicitly request 5/6/5 | ||||
|      */ | ||||
|     info.bits_per_pixel = 16; | ||||
|     info.red.offset     = 11; | ||||
|     info.red.length     = 5; | ||||
|     info.green.offset   = 5; | ||||
|     info.green.length   = 6; | ||||
|     info.blue.offset    = 0; | ||||
|     info.blue.length    = 5; | ||||
|     info.transp.offset  = 0; | ||||
|     info.transp.length  = 0; | ||||
|  | ||||
|     /* | ||||
|      * Request NUM_BUFFERS screens (at lest 2 for page flipping) | ||||
|      */ | ||||
|     info.yres_virtual = info.yres * NUM_BUFFERS; | ||||
|  | ||||
|  | ||||
|     uint32_t flags = PAGE_FLIP; | ||||
|     if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { | ||||
|         info.yres_virtual = info.yres; | ||||
|         flags &= ~PAGE_FLIP; | ||||
|         LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); | ||||
|     } | ||||
|  | ||||
|     if (info.yres_virtual < info.yres * 2) { | ||||
|         // we need at least 2 for page-flipping | ||||
|         info.yres_virtual = info.yres; | ||||
|         flags &= ~PAGE_FLIP; | ||||
|         LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", | ||||
|                 info.yres_virtual, info.yres*2); | ||||
|     } | ||||
|  | ||||
|     if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) | ||||
|         return -errno; | ||||
|  | ||||
|     int refreshRate = 1000000000000000LLU / | ||||
|     ( | ||||
|             uint64_t( info.upper_margin + info.lower_margin + info.yres ) | ||||
|             * ( info.left_margin  + info.right_margin + info.xres ) | ||||
|             * info.pixclock | ||||
|     ); | ||||
|  | ||||
|     if (refreshRate == 0) { | ||||
|         // bleagh, bad info from the driver | ||||
|         refreshRate = 60*1000;  // 60 Hz | ||||
|     } | ||||
|  | ||||
|     if (int(info.width) <= 0 || int(info.height) <= 0) { | ||||
|         // the driver doesn't return that information | ||||
|         // default to 160 dpi | ||||
|         info.width  = ((info.xres * 25.4f)/160.0f + 0.5f); | ||||
|         info.height = ((info.yres * 25.4f)/160.0f + 0.5f); | ||||
|     } | ||||
|  | ||||
|     float xdpi = (info.xres * 25.4f) / info.width; | ||||
|     float ydpi = (info.yres * 25.4f) / info.height; | ||||
|     float fps  = refreshRate / 1000.0f; | ||||
|  | ||||
|     LOGI(   "using (fd=%d)\n" | ||||
|             "id           = %s\n" | ||||
|             "xres         = %d px\n" | ||||
|             "yres         = %d px\n" | ||||
|             "xres_virtual = %d px\n" | ||||
|             "yres_virtual = %d px\n" | ||||
|             "bpp          = %d\n" | ||||
|             "r            = %2u:%u\n" | ||||
|             "g            = %2u:%u\n" | ||||
|             "b            = %2u:%u\n", | ||||
|             fd, | ||||
|             finfo.id, | ||||
|             info.xres, | ||||
|             info.yres, | ||||
|             info.xres_virtual, | ||||
|             info.yres_virtual, | ||||
|             info.bits_per_pixel, | ||||
|             info.red.offset, info.red.length, | ||||
|             info.green.offset, info.green.length, | ||||
|             info.blue.offset, info.blue.length | ||||
|     ); | ||||
|  | ||||
|     LOGI(   "width        = %d mm (%f dpi)\n" | ||||
|             "height       = %d mm (%f dpi)\n" | ||||
|             "refresh rate = %.2f Hz\n", | ||||
|             info.width,  xdpi, | ||||
|             info.height, ydpi, | ||||
|             fps | ||||
|     ); | ||||
|  | ||||
|  | ||||
|     if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) | ||||
|         return -errno; | ||||
|  | ||||
|     if (finfo.smem_len <= 0) | ||||
|         return -errno; | ||||
|  | ||||
|  | ||||
|     module->flags = flags; | ||||
|     module->info = info; | ||||
|     module->finfo = finfo; | ||||
|     module->xdpi = xdpi; | ||||
|     module->ydpi = ydpi; | ||||
|     module->fps = fps; | ||||
|  | ||||
|     /* | ||||
|      * map the framebuffer | ||||
|      */ | ||||
|  | ||||
|     int err; | ||||
|     size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); | ||||
|     module->framebuffer = new private_handle_t(dup(fd), fbSize, | ||||
|             private_handle_t::PRIV_FLAGS_USES_PMEM); | ||||
|  | ||||
|     module->numBuffers = info.yres_virtual / info.yres; | ||||
|     module->bufferMask = 0; | ||||
|  | ||||
|     void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | ||||
|     if (vaddr == MAP_FAILED) { | ||||
|         LOGE("Error mapping the framebuffer (%s)", strerror(errno)); | ||||
|         return -errno; | ||||
|     } | ||||
|     module->framebuffer->base = intptr_t(vaddr); | ||||
|     module->framebuffer->phys = intptr_t(finfo.smem_start); | ||||
|     memset(vaddr, 0, fbSize); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int mapFrameBuffer(struct private_module_t* module) | ||||
| { | ||||
|     pthread_mutex_lock(&module->lock); | ||||
|     int err = mapFrameBufferLocked(module); | ||||
|     pthread_mutex_unlock(&module->lock); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static int fb_close(struct hw_device_t *dev) | ||||
| { | ||||
|     fb_context_t* ctx = (fb_context_t*)dev; | ||||
|     if (ctx) { | ||||
|         free(ctx); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fb_device_open(hw_module_t const* module, const char* name, | ||||
|         hw_device_t** device) | ||||
| { | ||||
|     int status = -EINVAL; | ||||
|     if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { | ||||
|         alloc_device_t* gralloc_device; | ||||
|         status = gralloc_open(module, &gralloc_device); | ||||
|         if (status < 0) | ||||
|             return status; | ||||
|  | ||||
|         /* initialize our state here */ | ||||
|         fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); | ||||
|         memset(dev, 0, sizeof(*dev)); | ||||
|  | ||||
|         /* initialize the procs */ | ||||
|         dev->device.common.tag = HARDWARE_DEVICE_TAG; | ||||
|         dev->device.common.version = 0; | ||||
|         dev->device.common.module = const_cast<hw_module_t*>(module); | ||||
|         dev->device.common.close = fb_close; | ||||
|         dev->device.setSwapInterval = fb_setSwapInterval; | ||||
|         dev->device.post            = fb_post; | ||||
|         dev->device.setUpdateRect = 0; | ||||
|         dev->device.compositionComplete = fb_compositionComplete; | ||||
|  | ||||
|         private_module_t* m = (private_module_t*)module; | ||||
|         status = mapFrameBuffer(m); | ||||
|         if (status >= 0) { | ||||
|             int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); | ||||
|             const_cast<uint32_t&>(dev->device.flags) = 0; | ||||
|             const_cast<uint32_t&>(dev->device.width) = m->info.xres; | ||||
|             const_cast<uint32_t&>(dev->device.height) = m->info.yres; | ||||
|             const_cast<int&>(dev->device.stride) = stride; | ||||
|             const_cast<int&>(dev->device.format) = HAL_PIXEL_FORMAT_RGB_565; | ||||
|             const_cast<float&>(dev->device.xdpi) = m->xdpi; | ||||
|             const_cast<float&>(dev->device.ydpi) = m->ydpi; | ||||
|             const_cast<float&>(dev->device.fps) = m->fps; | ||||
|             const_cast<int&>(dev->device.minSwapInterval) = 1; | ||||
|             const_cast<int&>(dev->device.maxSwapInterval) = 1; | ||||
|  | ||||
|             if (m->finfo.reserved[0] == 0x5444 && | ||||
|                     m->finfo.reserved[1] == 0x5055) { | ||||
|                 dev->device.setUpdateRect = fb_setUpdateRect; | ||||
|                 LOGD("UPDATE_ON_DEMAND supported"); | ||||
|             } | ||||
|  | ||||
|             *device = &dev->device.common; | ||||
|         } | ||||
|     } | ||||
|     return status; | ||||
| } | ||||
|  | ||||
| /* Copy a pmem buffer to the framebuffer */ | ||||
|  | ||||
| static void | ||||
| msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, | ||||
|                 int x, int y, int w, int h) | ||||
| { | ||||
|     struct { | ||||
|         unsigned int count; | ||||
|         mdp_blit_req req; | ||||
|     } blit; | ||||
|     private_handle_t *priv = (private_handle_t*) handle; | ||||
|  | ||||
|     memset(&blit, 0, sizeof(blit)); | ||||
|     blit.count = 1; | ||||
|  | ||||
|     blit.req.flags = 0; | ||||
|     blit.req.alpha = 0xff; | ||||
|     blit.req.transp_mask = 0xffffffff; | ||||
|  | ||||
|     blit.req.src.width = width; | ||||
|     blit.req.src.height = height; | ||||
|     blit.req.src.offset = 0; | ||||
|     blit.req.src.memory_id = priv->fd; | ||||
|  | ||||
|     blit.req.dst.width = width; | ||||
|     blit.req.dst.height = height; | ||||
|     blit.req.dst.offset = 0; | ||||
|     blit.req.dst.memory_id = fd;  | ||||
|     blit.req.dst.format = MDP_RGB_565; | ||||
|  | ||||
|     blit.req.src_rect.x = blit.req.dst_rect.x = x; | ||||
|     blit.req.src_rect.y = blit.req.dst_rect.y = y; | ||||
|     blit.req.src_rect.w = blit.req.dst_rect.w = w; | ||||
|     blit.req.src_rect.h = blit.req.dst_rect.h = h; | ||||
|  | ||||
|     if (ioctl(fd, MSMFB_BLIT, &blit)) | ||||
|         LOGE("MSMFB_BLIT failed = %d", -errno); | ||||
| } | ||||
							
								
								
									
										63
									
								
								libgralloc-qsd8k/gr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								libgralloc-qsd8k/gr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef GR_H_ | ||||
| #define GR_H_ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #ifdef HAVE_ANDROID_OS      // just want PAGE_SIZE define | ||||
| # include <asm/page.h> | ||||
| #else | ||||
| # include <sys/user.h> | ||||
| #endif | ||||
| #include <limits.h> | ||||
| #include <sys/cdefs.h> | ||||
| #include <hardware/gralloc.h> | ||||
| #include <pthread.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include <cutils/native_handle.h> | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| struct private_module_t; | ||||
| struct private_handle_t; | ||||
|  | ||||
| inline size_t roundUpToPageSize(size_t x) { | ||||
|     return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); | ||||
| } | ||||
|  | ||||
| int mapFrameBufferLocked(struct private_module_t* module); | ||||
| int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| class Locker { | ||||
|     pthread_mutex_t mutex; | ||||
| public: | ||||
|     class Autolock { | ||||
|         Locker& locker; | ||||
|     public: | ||||
|         inline Autolock(Locker& locker) : locker(locker) {  locker.lock(); } | ||||
|         inline ~Autolock() { locker.unlock(); } | ||||
|     }; | ||||
|     inline Locker()        { pthread_mutex_init(&mutex, 0); } | ||||
|     inline ~Locker()       { pthread_mutex_destroy(&mutex); } | ||||
|     inline void lock()     { pthread_mutex_lock(&mutex); } | ||||
|     inline void unlock()   { pthread_mutex_unlock(&mutex); } | ||||
| }; | ||||
|  | ||||
| #endif /* GR_H_ */ | ||||
							
								
								
									
										490
									
								
								libgralloc-qsd8k/gralloc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										490
									
								
								libgralloc-qsd8k/gralloc.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,490 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #include <limits.h> | ||||
| #include <unistd.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <pthread.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <sys/mman.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/ioctl.h> | ||||
|  | ||||
| #include <cutils/ashmem.h> | ||||
| #include <cutils/log.h> | ||||
| #include <cutils/atomic.h> | ||||
|  | ||||
| #include <hardware/hardware.h> | ||||
| #include <hardware/gralloc.h> | ||||
|  | ||||
| #include "gralloc_priv.h" | ||||
| #include "allocator.h" | ||||
|  | ||||
| #if HAVE_ANDROID_OS | ||||
| #include <linux/android_pmem.h> | ||||
| #endif | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static SimpleBestFitAllocator sAllocator; | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| struct gralloc_context_t { | ||||
|     alloc_device_t  device; | ||||
|     /* our private data here */ | ||||
| }; | ||||
|  | ||||
| static int gralloc_alloc_buffer(alloc_device_t* dev, | ||||
|         size_t size, int usage, buffer_handle_t* pHandle); | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| int fb_device_open(const hw_module_t* module, const char* name, | ||||
|         hw_device_t** device); | ||||
|  | ||||
| static int gralloc_device_open(const hw_module_t* module, const char* name, | ||||
|         hw_device_t** device); | ||||
|  | ||||
| extern int gralloc_lock(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle, int usage, | ||||
|         int l, int t, int w, int h, | ||||
|         void** vaddr); | ||||
|  | ||||
| extern int gralloc_unlock(gralloc_module_t const* module,  | ||||
|         buffer_handle_t handle); | ||||
|  | ||||
| extern int gralloc_register_buffer(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle); | ||||
|  | ||||
| extern int gralloc_unregister_buffer(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle); | ||||
|  | ||||
| extern int gralloc_perform(struct gralloc_module_t const* module, | ||||
|         int operation, ... ); | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static struct hw_module_methods_t gralloc_module_methods = { | ||||
|         open: gralloc_device_open | ||||
| }; | ||||
|  | ||||
| struct private_module_t HAL_MODULE_INFO_SYM = { | ||||
|     base: { | ||||
|         common: { | ||||
|             tag: HARDWARE_MODULE_TAG, | ||||
|             version_major: 1, | ||||
|             version_minor: 0, | ||||
|             id: GRALLOC_HARDWARE_MODULE_ID, | ||||
|             name: "Graphics Memory Allocator Module", | ||||
|             author: "The Android Open Source Project", | ||||
|             methods: &gralloc_module_methods | ||||
|         }, | ||||
|         registerBuffer: gralloc_register_buffer, | ||||
|         unregisterBuffer: gralloc_unregister_buffer, | ||||
|         lock: gralloc_lock, | ||||
|         unlock: gralloc_unlock, | ||||
|         perform: gralloc_perform, | ||||
|     }, | ||||
|     framebuffer: 0, | ||||
|     flags: 0, | ||||
|     numBuffers: 0, | ||||
|     bufferMask: 0, | ||||
|     lock: PTHREAD_MUTEX_INITIALIZER, | ||||
|     currentBuffer: 0, | ||||
|     pmem_master: -1, | ||||
|     pmem_master_base: 0, | ||||
|     master_phys: 0 | ||||
| }; | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, | ||||
|         size_t size, int usage, buffer_handle_t* pHandle) | ||||
| { | ||||
|     private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|             dev->common.module); | ||||
|  | ||||
|     // allocate the framebuffer | ||||
|     if (m->framebuffer == NULL) { | ||||
|         // initialize the framebuffer, the framebuffer is mapped once | ||||
|         // and forever. | ||||
|         int err = mapFrameBufferLocked(m); | ||||
|         if (err < 0) { | ||||
|             return err; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const uint32_t bufferMask = m->bufferMask; | ||||
|     const uint32_t numBuffers = m->numBuffers; | ||||
|     const size_t bufferSize = m->finfo.line_length * m->info.yres; | ||||
|     if (numBuffers == 1) { | ||||
|         // If we have only one buffer, we never use page-flipping. Instead, | ||||
|         // we return a regular buffer which will be memcpy'ed to the main | ||||
|         // screen when post is called. | ||||
|         int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; | ||||
|         return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle); | ||||
|     } | ||||
|  | ||||
|     if (bufferMask >= ((1LU<<numBuffers)-1)) { | ||||
|         // We ran out of buffers. | ||||
|         return -ENOMEM; | ||||
|     } | ||||
|  | ||||
|     // create a "fake" handles for it | ||||
|     intptr_t vaddr = intptr_t(m->framebuffer->base); | ||||
|     private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, | ||||
|             private_handle_t::PRIV_FLAGS_USES_PMEM | | ||||
|             private_handle_t::PRIV_FLAGS_FRAMEBUFFER); | ||||
|  | ||||
|     // find a free slot | ||||
|     for (uint32_t i=0 ; i<numBuffers ; i++) { | ||||
|         if ((bufferMask & (1LU<<i)) == 0) { | ||||
|             m->bufferMask |= (1LU<<i); | ||||
|             break; | ||||
|         } | ||||
|         vaddr += bufferSize; | ||||
|     } | ||||
|      | ||||
|     hnd->base = vaddr; | ||||
|     hnd->offset = vaddr - intptr_t(m->framebuffer->base); | ||||
|     hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; | ||||
|     *pHandle = hnd; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int gralloc_alloc_framebuffer(alloc_device_t* dev, | ||||
|         size_t size, int usage, buffer_handle_t* pHandle) | ||||
| { | ||||
|     private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|             dev->common.module); | ||||
|     pthread_mutex_lock(&m->lock); | ||||
|     int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); | ||||
|     pthread_mutex_unlock(&m->lock); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int init_pmem_area_locked(private_module_t* m) | ||||
| { | ||||
|     int err = 0; | ||||
|     int master_fd = open("/dev/pmem", O_RDWR, 0); | ||||
|     if (master_fd >= 0) { | ||||
|         size_t size; | ||||
|         pmem_region region; | ||||
|         if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { | ||||
|             LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode"); | ||||
|             size = 8<<20;   // 8 MiB | ||||
|         } else { | ||||
|             size = region.len; | ||||
|         } | ||||
|         sAllocator.setSize(size); | ||||
|  | ||||
|         void* base = mmap(0, size,  | ||||
|                 PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); | ||||
|         if (base == MAP_FAILED) { | ||||
|             err = -errno; | ||||
|             base = 0; | ||||
|             close(master_fd); | ||||
|             master_fd = -1; | ||||
|         } else { | ||||
|             // FIXME: get physical address, eventually this will have to go away | ||||
|             pmem_region region; | ||||
|             err = ioctl(master_fd, PMEM_GET_PHYS, ®ion); | ||||
|             if (err < 0) { | ||||
|                 LOGE("PMEM_GET_PHYS failed (%s)", strerror(-errno)); | ||||
|             } else { | ||||
|                 m->master_phys = (unsigned long)region.offset; | ||||
|             } | ||||
|         } | ||||
|         m->pmem_master = master_fd; | ||||
|         m->pmem_master_base = base; | ||||
|     } else { | ||||
|         err = -errno; | ||||
|     } | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| static int init_pmem_area(private_module_t* m) | ||||
| { | ||||
|     pthread_mutex_lock(&m->lock); | ||||
|     int err = m->pmem_master; | ||||
|     if (err == -1) { | ||||
|         // first time, try to initialize pmem | ||||
|         err = init_pmem_area_locked(m); | ||||
|         if (err) { | ||||
|             m->pmem_master = err; | ||||
|         } | ||||
|     } else if (err < 0) { | ||||
|         // pmem couldn't be initialized, never use it | ||||
|     } else { | ||||
|         // pmem OK | ||||
|         err = 0; | ||||
|     } | ||||
|     pthread_mutex_unlock(&m->lock); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| static int gralloc_alloc_buffer(alloc_device_t* dev, | ||||
|         size_t size, int usage, buffer_handle_t* pHandle) | ||||
| { | ||||
|     int err = 0; | ||||
|     int flags = 0; | ||||
|  | ||||
|     int fd = -1; | ||||
|     void* base = 0; | ||||
|     int offset = 0; | ||||
|     int lockState = 0; | ||||
|  | ||||
|     size = roundUpToPageSize(size); | ||||
|      | ||||
|     if (usage & GRALLOC_USAGE_HW_TEXTURE) { | ||||
|         // enable pmem in that case, so our software GL can fallback to | ||||
|         // the copybit module. | ||||
|         flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; | ||||
|     } | ||||
|      | ||||
|     if (usage & GRALLOC_USAGE_HW_2D) { | ||||
|         flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; | ||||
|     } | ||||
|  | ||||
|     if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) { | ||||
| try_ashmem: | ||||
|         fd = ashmem_create_region("gralloc-buffer", size); | ||||
|         if (fd < 0) { | ||||
|             LOGE("couldn't create ashmem (%s)", strerror(errno)); | ||||
|             err = -errno; | ||||
|         } | ||||
|     } else { | ||||
|         private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|                 dev->common.module); | ||||
|  | ||||
|         err = init_pmem_area(m); | ||||
|         if (err == 0) { | ||||
|             // PMEM buffers are always mmapped | ||||
|             base = m->pmem_master_base; | ||||
|             lockState |= private_handle_t::LOCK_STATE_MAPPED; | ||||
|  | ||||
|             offset = sAllocator.allocate(size); | ||||
|             if (offset < 0) { | ||||
|                 // no more pmem memory | ||||
|                 err = -ENOMEM; | ||||
|             } else { | ||||
|                 struct pmem_region sub = { offset, size }; | ||||
|                  | ||||
|                 // now create the "sub-heap" | ||||
|                 fd = open("/dev/pmem", O_RDWR, 0); | ||||
|                 err = fd < 0 ? fd : 0; | ||||
|                  | ||||
|                 // and connect to it | ||||
|                 if (err == 0) | ||||
|                     err = ioctl(fd, PMEM_CONNECT, m->pmem_master); | ||||
|  | ||||
|                 // and make it available to the client process | ||||
|                 if (err == 0) | ||||
|                     err = ioctl(fd, PMEM_MAP, &sub); | ||||
|  | ||||
|                 if (err < 0) { | ||||
|                     err = -errno; | ||||
|                     close(fd); | ||||
|                     sAllocator.deallocate(offset); | ||||
|                     fd = -1; | ||||
|                 } | ||||
|                 memset((char*)base + offset, 0, size); | ||||
|                 //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); | ||||
|             } | ||||
|         } else { | ||||
|             if ((usage & GRALLOC_USAGE_HW_2D) == 0) { | ||||
|                 // the caller didn't request PMEM, so we can try something else | ||||
|                 flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; | ||||
|                 err = 0; | ||||
|                 goto try_ashmem; | ||||
|             } else { | ||||
|                 LOGE("couldn't open pmem (%s)", strerror(errno)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (err == 0) { | ||||
|         private_handle_t* hnd = new private_handle_t(fd, size, flags); | ||||
|         hnd->offset = offset; | ||||
|         hnd->base = int(base)+offset; | ||||
|         hnd->lockState = lockState; | ||||
|         if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { | ||||
|             private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|                     dev->common.module); | ||||
|             hnd->phys = m->master_phys + offset; | ||||
|         } | ||||
|         *pHandle = hnd; | ||||
|     } | ||||
|      | ||||
|     LOGE_IF(err, "gralloc failed err=%s", strerror(-err)); | ||||
|      | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static int gralloc_alloc(alloc_device_t* dev, | ||||
|         int w, int h, int format, int usage, | ||||
|         buffer_handle_t* pHandle, int* pStride) | ||||
| { | ||||
|     if (!pHandle || !pStride) | ||||
|         return -EINVAL; | ||||
|  | ||||
|     size_t size, alignedw, alignedh; | ||||
|     if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP ||  | ||||
|             format == HAL_PIXEL_FORMAT_YCbCr_422_SP)  | ||||
|     { | ||||
|         // FIXME: there is no way to return the alignedh | ||||
|         alignedw = (w + 1) & ~1; | ||||
|         switch (format) { | ||||
|             case HAL_PIXEL_FORMAT_YCbCr_420_SP: | ||||
|                 size = alignedw * h * 2; | ||||
|                 break; | ||||
|             case HAL_PIXEL_FORMAT_YCbCr_422_SP: | ||||
|                 alignedh = (h+1) & ~1; | ||||
|                 size = (alignedw * alignedh) + (w/2 * h/2) * 2; | ||||
|                 break; | ||||
|             default: | ||||
|                 return -EINVAL; | ||||
|         } | ||||
|     } else { | ||||
|         alignedw = (w + 31) & ~31; | ||||
|         alignedh = (h + 31) & ~31; | ||||
|         int bpp = 0; | ||||
|         switch (format) { | ||||
|             case HAL_PIXEL_FORMAT_RGBA_8888: | ||||
|             case HAL_PIXEL_FORMAT_RGBX_8888: | ||||
|             case HAL_PIXEL_FORMAT_BGRA_8888: | ||||
|                 bpp = 4; | ||||
|                 break; | ||||
|             case HAL_PIXEL_FORMAT_RGB_888: | ||||
|                 bpp = 3; | ||||
|                 break; | ||||
|             case HAL_PIXEL_FORMAT_RGB_565: | ||||
|             case HAL_PIXEL_FORMAT_RGBA_5551: | ||||
|             case HAL_PIXEL_FORMAT_RGBA_4444: | ||||
|                 bpp = 2; | ||||
|                 break; | ||||
|             default: | ||||
|                 return -EINVAL; | ||||
|         } | ||||
|         size = alignedw * alignedh * bpp; | ||||
|     } | ||||
|  | ||||
|     int err; | ||||
|     if (usage & GRALLOC_USAGE_HW_FB) { | ||||
|         err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); | ||||
|     } else { | ||||
|         err = gralloc_alloc_buffer(dev, size, usage, pHandle); | ||||
|     } | ||||
|  | ||||
|     if (err < 0) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     *pStride = alignedw; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int gralloc_free(alloc_device_t* dev, | ||||
|         buffer_handle_t handle) | ||||
| { | ||||
|     if (private_handle_t::validate(handle) < 0) | ||||
|         return -EINVAL; | ||||
|  | ||||
|     private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle); | ||||
|     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { | ||||
|         // free this buffer | ||||
|         private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|                 dev->common.module); | ||||
|         const size_t bufferSize = m->finfo.line_length * m->info.yres; | ||||
|         int index = (hnd->base - m->framebuffer->base) / bufferSize; | ||||
|         m->bufferMask &= ~(1<<index);  | ||||
|     } else {  | ||||
|         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { | ||||
|             if (hnd->fd >= 0) { | ||||
|                 struct pmem_region sub = { hnd->offset, hnd->size }; | ||||
|                 int err = ioctl(hnd->fd, PMEM_UNMAP, &sub); | ||||
|                 LOGE_IF(err<0, "PMEM_UNMAP failed (%s), " | ||||
|                         "fd=%d, sub.offset=%lu, sub.size=%lu", | ||||
|                         strerror(errno), hnd->fd, hnd->offset, hnd->size); | ||||
|                 if (err == 0) { | ||||
|                     // we can't deallocate the memory in case of UNMAP failure | ||||
|                     // because it would give that process access to someone else's | ||||
|                     // surfaces, which would be a security breach. | ||||
|                     sAllocator.deallocate(hnd->offset); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( | ||||
|                 dev->common.module); | ||||
|         terminateBuffer(module, const_cast<private_handle_t*>(hnd)); | ||||
|     } | ||||
|  | ||||
|     close(hnd->fd); | ||||
|     delete hnd; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static int gralloc_close(struct hw_device_t *dev) | ||||
| { | ||||
|     gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev); | ||||
|     if (ctx) { | ||||
|         /* TODO: keep a list of all buffer_handle_t created, and free them | ||||
|          * all here. | ||||
|          */ | ||||
|         free(ctx); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int gralloc_device_open(const hw_module_t* module, const char* name, | ||||
|         hw_device_t** device) | ||||
| { | ||||
|     int status = -EINVAL; | ||||
|     if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { | ||||
|         gralloc_context_t *dev; | ||||
|         dev = (gralloc_context_t*)malloc(sizeof(*dev)); | ||||
|  | ||||
|         /* initialize our state here */ | ||||
|         memset(dev, 0, sizeof(*dev)); | ||||
|  | ||||
|         /* initialize the procs */ | ||||
|         dev->device.common.tag = HARDWARE_DEVICE_TAG; | ||||
|         dev->device.common.version = 0; | ||||
|         dev->device.common.module = const_cast<hw_module_t*>(module); | ||||
|         dev->device.common.close = gralloc_close; | ||||
|  | ||||
|         dev->device.alloc   = gralloc_alloc; | ||||
|         dev->device.free    = gralloc_free; | ||||
|  | ||||
|         *device = &dev->device.common; | ||||
|         status = 0; | ||||
|     } else { | ||||
|         status = fb_device_open(module, name, device); | ||||
|     } | ||||
|     return status; | ||||
| } | ||||
							
								
								
									
										140
									
								
								libgralloc-qsd8k/gralloc_priv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								libgralloc-qsd8k/gralloc_priv.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef GRALLOC_PRIV_H_ | ||||
| #define GRALLOC_PRIV_H_ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <limits.h> | ||||
| #include <sys/cdefs.h> | ||||
| #include <hardware/gralloc.h> | ||||
| #include <pthread.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include <cutils/native_handle.h> | ||||
|  | ||||
| #include <linux/fb.h> | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| struct private_module_t; | ||||
| struct private_handle_t; | ||||
|  | ||||
| struct private_module_t { | ||||
|     gralloc_module_t base; | ||||
|  | ||||
|     struct private_handle_t* framebuffer; | ||||
|     uint32_t flags; | ||||
|     uint32_t numBuffers; | ||||
|     uint32_t bufferMask; | ||||
|     pthread_mutex_t lock; | ||||
|     buffer_handle_t currentBuffer; | ||||
|     int pmem_master; | ||||
|     void* pmem_master_base; | ||||
|     unsigned long master_phys; | ||||
|  | ||||
|     struct fb_var_screeninfo info; | ||||
|     struct fb_fix_screeninfo finfo; | ||||
|     float xdpi; | ||||
|     float ydpi; | ||||
|     float fps; | ||||
|      | ||||
|     enum { | ||||
|         // flag to indicate we'll post this buffer | ||||
|         PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| struct private_handle_t : public native_handle { | ||||
| #else | ||||
| struct private_handle_t { | ||||
|     native_handle_t nativeHandle; | ||||
| #endif | ||||
|      | ||||
|     enum { | ||||
|         PRIV_FLAGS_FRAMEBUFFER = 0x00000001, | ||||
|         PRIV_FLAGS_USES_PMEM   = 0x00000002, | ||||
|     }; | ||||
|  | ||||
|     enum { | ||||
|         LOCK_STATE_WRITE     =   1<<31, | ||||
|         LOCK_STATE_MAPPED    =   1<<30, | ||||
|         LOCK_STATE_READ_MASK =   0x3FFFFFFF | ||||
|     }; | ||||
|  | ||||
|     // file-descriptors | ||||
|     int     fd; | ||||
|     // ints | ||||
|     int     magic; | ||||
|     int     flags; | ||||
|     int     size; | ||||
|     int     offset; | ||||
|     int     gpu_fd; // stored as an int, b/c we don't want it marshalled | ||||
|  | ||||
|     // FIXME: the attributes below should be out-of-line | ||||
|     int     base; | ||||
|     int     lockState; | ||||
|     int     writeOwner; | ||||
|     int     phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care | ||||
|     int     pid; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|     static const int sNumInts = 10; | ||||
|     static const int sNumFds = 1; | ||||
|     static const int sMagic = 'gmsm'; | ||||
|  | ||||
|     private_handle_t(int fd, int size, int flags) : | ||||
|         fd(fd), magic(sMagic), flags(flags), size(size), offset(0), gpu_fd(-1), | ||||
|         base(0), lockState(0), writeOwner(0), phys(0), pid(getpid()) | ||||
|     { | ||||
|         version = sizeof(native_handle); | ||||
|         numInts = sNumInts; | ||||
|         numFds = sNumFds; | ||||
|     } | ||||
|     ~private_handle_t() { | ||||
|         magic = 0; | ||||
|     } | ||||
|  | ||||
|     bool usesPhysicallyContiguousMemory() { | ||||
|         return (flags & PRIV_FLAGS_USES_PMEM) != 0; | ||||
|     } | ||||
|  | ||||
|     static int validate(const native_handle* h) { | ||||
|         const private_handle_t* hnd = (const private_handle_t*)h; | ||||
|         if (!h || h->version != sizeof(native_handle) || | ||||
|                 h->numInts != sNumInts || h->numFds != sNumFds || | ||||
|                 hnd->magic != sMagic)  | ||||
|         { | ||||
|             LOGE("invalid gralloc handle (at %p)", h); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     static private_handle_t* dynamicCast(const native_handle* in) { | ||||
|         if (validate(in) == 0) { | ||||
|             return (private_handle_t*) in; | ||||
|         } | ||||
|         return NULL; | ||||
|     } | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| #endif /* GRALLOC_PRIV_H_ */ | ||||
							
								
								
									
										322
									
								
								libgralloc-qsd8k/mapper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								libgralloc-qsd8k/mapper.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,322 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #include <limits.h> | ||||
| #include <errno.h> | ||||
| #include <pthread.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <stdarg.h> | ||||
|  | ||||
| #include <sys/mman.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include <cutils/log.h> | ||||
| #include <cutils/atomic.h> | ||||
|  | ||||
| #include <hardware/hardware.h> | ||||
| #include <hardware/gralloc.h> | ||||
|  | ||||
| #include "gralloc_priv.h" | ||||
|  | ||||
|  | ||||
| // we need this for now because pmem cannot mmap at an offset | ||||
| #define PMEM_HACK   1 | ||||
|  | ||||
| /* desktop Linux needs a little help with gettid() */ | ||||
| #if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS) | ||||
| #define __KERNEL__ | ||||
| # include <linux/unistd.h> | ||||
| pid_t gettid() { return syscall(__NR_gettid);} | ||||
| #undef __KERNEL__ | ||||
| #endif | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static int gralloc_map(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle, | ||||
|         void** vaddr) | ||||
| { | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { | ||||
|         size_t size = hnd->size; | ||||
| #if PMEM_HACK | ||||
|         size += hnd->offset; | ||||
| #endif | ||||
|         void* mappedAddress = mmap(0, size, | ||||
|                 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); | ||||
|         if (mappedAddress == MAP_FAILED) { | ||||
|             LOGE("Could not mmap handle %p, fd=%d (%s)", | ||||
|                     handle, hnd->fd, strerror(errno)); | ||||
|             hnd->base = 0; | ||||
|             return -errno; | ||||
|         } | ||||
|         hnd->base = intptr_t(mappedAddress) + hnd->offset; | ||||
|         //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",  | ||||
|         //        hnd->fd, hnd->offset, hnd->size, mappedAddress); | ||||
|     } | ||||
|     *vaddr = (void*)hnd->base; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int gralloc_unmap(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle) | ||||
| { | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { | ||||
|         void* base = (void*)hnd->base; | ||||
|         size_t size = hnd->size; | ||||
| #if PMEM_HACK | ||||
|         base = (void*)(intptr_t(base) - hnd->offset); | ||||
|         size += hnd->offset; | ||||
| #endif | ||||
|         //LOGD("unmapping from %p, size=%d", base, size); | ||||
|         if (munmap(base, size) < 0) { | ||||
|             LOGE("Could not unmap %s", strerror(errno)); | ||||
|         } | ||||
|     } | ||||
|     hnd->base = 0; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;  | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| int gralloc_register_buffer(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle) | ||||
| { | ||||
|     if (private_handle_t::validate(handle) < 0) | ||||
|         return -EINVAL; | ||||
|  | ||||
|     // In this implementation, we don't need to do anything here | ||||
|  | ||||
|     /* NOTE: we need to initialize the buffer as not mapped/not locked | ||||
|      * because it shouldn't when this function is called the first time | ||||
|      * in a new process. Ideally these flags shouldn't be part of the | ||||
|      * handle, but instead maintained in the kernel or at least  | ||||
|      * out-of-line | ||||
|      */  | ||||
|  | ||||
|     // if this handle was created in this process, then we keep it as is. | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     if (hnd->pid != getpid()) { | ||||
|         hnd->base = 0; | ||||
|         hnd->lockState  = 0; | ||||
|         hnd->writeOwner = 0; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int gralloc_unregister_buffer(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle) | ||||
| { | ||||
|     if (private_handle_t::validate(handle) < 0) | ||||
|         return -EINVAL; | ||||
|  | ||||
|     /* | ||||
|      * If the buffer has been mapped during a lock operation, it's time | ||||
|      * to un-map it. It's an error to be here with a locked buffer. | ||||
|      * NOTE: the framebuffer is handled differently and is never unmapped. | ||||
|      */ | ||||
|  | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|      | ||||
|     LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, | ||||
|             "[unregister] handle %p still locked (state=%08x)", | ||||
|             hnd, hnd->lockState); | ||||
|  | ||||
|     // never unmap buffers that were created in this process | ||||
|     if (hnd->pid != getpid()) { | ||||
|         if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { | ||||
|             gralloc_unmap(module, handle); | ||||
|         } | ||||
|         hnd->base = 0; | ||||
|         hnd->lockState  = 0; | ||||
|         hnd->writeOwner = 0; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int terminateBuffer(gralloc_module_t const* module, | ||||
|         private_handle_t* hnd) | ||||
| { | ||||
|     /* | ||||
|      * If the buffer has been mapped during a lock operation, it's time | ||||
|      * to un-map it. It's an error to be here with a locked buffer. | ||||
|      */ | ||||
|  | ||||
|     LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, | ||||
|             "[terminate] handle %p still locked (state=%08x)", | ||||
|             hnd, hnd->lockState); | ||||
|  | ||||
|     if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { | ||||
|         // this buffer was mapped, unmap it now | ||||
|         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { | ||||
|             if (hnd->pid != getpid()) { | ||||
|                 // ... unless it's a "master" pmem buffer, that is a buffer | ||||
|                 // mapped in the process it's been allocated. | ||||
|                 // (see gralloc_alloc_buffer()) | ||||
|                 gralloc_unmap(module, hnd); | ||||
|             } | ||||
|         } else { | ||||
|             gralloc_unmap(module, hnd); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int gralloc_lock(gralloc_module_t const* module, | ||||
|         buffer_handle_t handle, int usage, | ||||
|         int l, int t, int w, int h, | ||||
|         void** vaddr) | ||||
| { | ||||
|     if (private_handle_t::validate(handle) < 0) | ||||
|         return -EINVAL; | ||||
|  | ||||
|     int err = 0; | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     int32_t current_value, new_value; | ||||
|     int retry; | ||||
|  | ||||
|     do { | ||||
|         current_value = hnd->lockState; | ||||
|         new_value = current_value; | ||||
|  | ||||
|         if (current_value & private_handle_t::LOCK_STATE_WRITE) { | ||||
|             // already locked for write  | ||||
|             LOGE("handle %p already locked for write", handle); | ||||
|             return -EBUSY; | ||||
|         } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) { | ||||
|             // already locked for read | ||||
|             if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { | ||||
|                 LOGE("handle %p already locked for read", handle); | ||||
|                 return -EBUSY; | ||||
|             } else { | ||||
|                 // this is not an error | ||||
|                 //LOGD("%p already locked for read... count = %d",  | ||||
|                 //        handle, (current_value & ~(1<<31))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // not currently locked | ||||
|         if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { | ||||
|             // locking for write | ||||
|             new_value |= private_handle_t::LOCK_STATE_WRITE; | ||||
|         } | ||||
|         new_value++; | ||||
|  | ||||
|         retry = android_atomic_cmpxchg(current_value, new_value,  | ||||
|                 (volatile int32_t*)&hnd->lockState); | ||||
|     } while (retry); | ||||
|  | ||||
|     if (new_value & private_handle_t::LOCK_STATE_WRITE) { | ||||
|         // locking for write, store the tid | ||||
|         hnd->writeOwner = gettid(); | ||||
|     } | ||||
|  | ||||
|     if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { | ||||
|         if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { | ||||
|             // we need to map for real | ||||
|             pthread_mutex_t* const lock = &sMapLock; | ||||
|             pthread_mutex_lock(lock); | ||||
|             if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { | ||||
|                 err = gralloc_map(module, handle, vaddr); | ||||
|                 if (err == 0) { | ||||
|                     android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, | ||||
|                             (volatile int32_t*)&(hnd->lockState)); | ||||
|                 } | ||||
|             } | ||||
|             pthread_mutex_unlock(lock); | ||||
|         } | ||||
|         *vaddr = (void*)hnd->base; | ||||
|     } | ||||
|  | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| int gralloc_unlock(gralloc_module_t const* module,  | ||||
|         buffer_handle_t handle) | ||||
| { | ||||
|     if (private_handle_t::validate(handle) < 0) | ||||
|         return -EINVAL; | ||||
|  | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     int32_t current_value, new_value; | ||||
|  | ||||
|     do { | ||||
|         current_value = hnd->lockState; | ||||
|         new_value = current_value; | ||||
|  | ||||
|         if (current_value & private_handle_t::LOCK_STATE_WRITE) { | ||||
|             // locked for write | ||||
|             if (hnd->writeOwner == gettid()) { | ||||
|                 hnd->writeOwner = 0; | ||||
|                 new_value &= ~private_handle_t::LOCK_STATE_WRITE; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { | ||||
|             LOGE("handle %p not locked", handle); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|  | ||||
|         new_value--; | ||||
|  | ||||
|     } while (android_atomic_cmpxchg(current_value, new_value,  | ||||
|             (volatile int32_t*)&hnd->lockState)); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| int gralloc_perform(struct gralloc_module_t const* module, | ||||
|         int operation, ... ) | ||||
| { | ||||
|     int res = -EINVAL; | ||||
|     va_list args; | ||||
|     va_start(args, operation); | ||||
|  | ||||
|     switch (operation) { | ||||
|         case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: { | ||||
|             int fd = va_arg(args, int); | ||||
|             size_t size = va_arg(args, size_t); | ||||
|             size_t offset = va_arg(args, size_t); | ||||
|             void* base = va_arg(args, void*); | ||||
|             native_handle_t** handle = va_arg(args, native_handle_t**); | ||||
|             private_handle_t* hnd = (private_handle_t*)native_handle_create( | ||||
|                     private_handle_t::sNumFds, private_handle_t::sNumInts); | ||||
|             hnd->magic = private_handle_t::sMagic; | ||||
|             hnd->fd = fd; | ||||
|             hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM; | ||||
|             hnd->size = size; | ||||
|             hnd->offset = offset; | ||||
|             hnd->base = intptr_t(base) + offset; | ||||
|             hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; | ||||
|             *handle = (native_handle_t *)hnd; | ||||
|             res = 0; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     va_end(args); | ||||
|     return res; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user