Android 用户进程绘制过程.doc_第1页
Android 用户进程绘制过程.doc_第2页
Android 用户进程绘制过程.doc_第3页
Android 用户进程绘制过程.doc_第4页
Android 用户进程绘制过程.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android 用户进程绘制过程下面我们来看下这个函数,它先调用了Surface的lockCanvas获取一个Canvas,然后再调用surface.unlockCanvasAndPost来表示绘制结束。cpp view plain copy 在CODE上查看代码片派生到我的代码片private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff, boolean scalingRequired, Rect dirty) / Draw with software renderer. final Canvas canvas; try final int left = dirty.left; final int top = dirty.top; final int right = dirty.right; final int bottom = dirty.bottom; canvas = mSurface.lockCanvas(dirty);/获取一个Canvas . finally try surface.unlockCanvasAndPost(canvas);/绘制结束 catch (IllegalArgumentException e) Log.e(TAG, Could not unlock surface, e); mLayoutRequested = true; / ask wm for a new surface next time. /noinspection ReturnInsideFinallyBlock return false; if (LOCAL_LOGV) Log.v(TAG, Surface + surface + unlockCanvasAndPost); return true; 一、应用进程申请buffer我们先来看Surface的lockCanvas函数,其调用了native函数nativeLockCanvascpp view plain copy 在CODE上查看代码片派生到我的代码片public Canvas lockCanvas(Rect inOutDirty) throws Surface.OutOfResourcesException, IllegalArgumentException synchronized (mLock) checkNotReleasedLocked(); if (mLockedObject != 0) / Ideally, nativeLockCanvas() would throw in this situation and prevent the / double-lock, but that wont happen if mNativeObject was updated. We cant / abandon the old mLockedObject because it might still be in use, so instead / we just refuse to re-lock the Surface. throw new IllegalArgumentException(Surface was already locked); mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty); return mCanvas; 这个函数在android_view_Surface.cpp中,这个函数内容很多,我们先调用了Surface的lock函数来申请buffer,然后新建了一个SkBitmap,设置了内存地址,并且把这个bitmap放入了Canvas中。cpp view plain copy 在CODE上查看代码片派生到我的代码片static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) sp surface(reinterpret_cast(nativeObject); if (!isSurfaceValid(surface) doThrowIAE(env); return 0; Rect dirtyRect; Rect* dirtyRectPtr = NULL; if (dirtyRectObj) dirtyRect.left = env-GetIntField(dirtyRectObj, gRectClassInfo.left); dirtyRect.top = env-GetIntField(dirtyRectObj, gRectClassInfo.top); dirtyRect.right = env-GetIntField(dirtyRectObj, gRectClassInfo.right); dirtyRect.bottom = env-GetIntField(dirtyRectObj, gRectClassInfo.bottom); dirtyRectPtr = &dirtyRect; ANativeWindow_Buffer outBuffer; status_t err = surface-lock(&outBuffer, dirtyRectPtr);/从SurfaceFlinger中申请内存buffer if (err 0 & outBuffer.height 0) bitmap.setPixels(outBuffer.bits);/bitmap设置其内存地址 else / be safe with an empty bitmap. bitmap.setPixels(NULL); Canvas* nativeCanvas = GraphicsJNI:getNativeCanvas(env, canvasObj); nativeCanvas-setBitmap(bitmap);/设置Canvas的bitmap if (dirtyRectPtr) nativeCanvas-clipRect(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); if (dirtyRectObj) env-SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left); env-SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top); env-SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right); env-SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom); / Create another reference to the surface and return it. This reference / should be passed to nativeUnlockCanvasAndPost in place of mNativeObject, / because the latter could be replaced while the surface is locked. sp lockedSurface(surface); lockedSurface-incStrong(&sRefBaseOwner); return (jlong) lockedSurface.get(); 我们先来看下Surface的lock函数,先是调用了dequeueBuffer来申请内存,然后放入backBuffer。后面调用GraphicBuffer的lockAsync来把Buffer中的handle的地址放到vaddr中,最后把vaddr放到outBuffer的bits中。cpp view plain copy 在CODE上查看代码片派生到我的代码片status_t Surface:lock( ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) . ANativeWindowBuffer* out; int fenceFd = -1; status_t err = dequeueBuffer(&out, &fenceFd);/申请内存 if (err = NO_ERROR) sp backBuffer(GraphicBuffer:getSelf(out);/放到backBuffer中 const Rect bounds(backBuffer-width, backBuffer-height); . void* vaddr; status_t res = backBuffer-lockAsync(/这个函数就是把buffer的handle中的地址传到vaddr中 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, newDirtyRegion.bounds(), &vaddr, fenceFd); ALOGW_IF(res, failed locking buffer (handle = %p), backBuffer-handle); if (res != 0) err = INVALID_OPERATION; else mLockedBuffer = backBuffer; outBuffer-width = backBuffer-width; outBuffer-height = backBuffer-height; outBuffer-stride = backBuffer-stride; outBuffer-format = backBuffer-format; outBuffer-bits = vaddr;/buffer地址 return err; 1.1 申请bufferSurface的dequeueBuffer函数主要就是从SurfaceFlinger中申请buffer。cpp view plain copy 在CODE上查看代码片派生到我的代码片int Surface:dequeueBuffer(android_native_buffer_t* buffer, int* fenceFd) ATRACE_CALL(); ALOGV(Surface:dequeueBuffer); uint32_t reqWidth; uint32_t reqHeight; bool swapIntervalZero; PixelFormat reqFormat; uint32_t reqUsage; . int buf = -1; sp fence; status_t result = mGraphicBufferProducer-dequeueBuffer(&buf, &fence, swapIntervalZero,/在SurfaceFlinger中申请内存,只要返回mSlots中的序号 reqWidth, reqHeight, reqFormat, reqUsage); Mutex:Autolock lock(mMutex); sp& gbuf(mSlotsbuf.buffer); if (result & IGraphicBufferProducer:RELEASE_ALL_BUFFERS) freeAllBuffers(); if (result & IGraphicBufferProducer:BUFFER_NEEDS_REALLOCATION) | gbuf = 0) result = mGraphicBufferProducer-requestBuffer(buf, &gbuf);/根据需要拿到buffer . . *buffer = gbuf.get(); return OK; 下面我们再看下SurfaceFlinger中对应的dequeueBuffer和requestBuffer函数。我们先看BufferQueueProducer.cpp中dequeueBuffer关于分配buffer的一段代码:cpp view plain copy 在CODE上查看代码片派生到我的代码片. if (returnFlags & BUFFER_NEEDS_REALLOCATION) /需要分配内存 status_t error; BQ_LOGV(dequeueBuffer: allocating a new buffer for slot %d, *outSlot); sp graphicBuffer(mCore-mAllocator-createGraphicBuffer( width, height, format, usage, &error); if (graphicBuffer = NULL) BQ_LOGE(dequeueBuffer: createGraphicBuffer failed); return error; / Autolock scope Mutex:Autolock lock(mCore-mMutex); if (mCore-mIsAbandoned) BQ_LOGE(dequeueBuffer: BufferQueue has been abandoned); return NO_INIT; graphicBuffer-setGenerationNumber(mCore-mGenerationNumber); mSlots*outSlot.mGraphicBuffer = graphicBuffer;/将分配的内存放到mSlots中,outSlot就是给应用进程mSlots的序号 / Autolock scope . return returnFlags; 然后我们再来看其requestBuffer函数,就是根据序号,从mSlots拿到buffer。cpp view plain copy 在CODE上查看代码片派生到我的代码片status_t BufferQueueProducer:requestBuffer(int slot, sp* buf) ATRACE_CALL(); BQ_LOGV(requestBuffer: slot %d, slot); Mutex:Autolock lock(mCore-mMutex); if (mCore-mIsAbandoned) BQ_LOGE(requestBuffer: BufferQueue has been abandoned); return NO_INIT; if (slot = BufferQueueDefs:NUM_BUFFER_SLOTS) BQ_LOGE(requestBuffer: slot index %d out of range 0, %d), slot, BufferQueueDefs:NUM_BUFFER_SLOTS); return BAD_VALUE; else if (mSlotsslot.mBufferState != BufferSlot:DEQUEUED) BQ_LOGE(requestBuffer: slot %d is not owned by the producer (state = %d), slot, mSlotsslot.mBufferState); return BAD_VALUE; mSlotsslot.mRequestBufferCalled = true; *buf = mSlotsslot.mGraphicBuffer; return NO_ERROR; 1.2 将buffer的地址放到vaddr中我们继续分析Surface的lock函数,来看下GraphicBuffer的lockAsyc,其调用了getBufferMapper().lockAsync,而这个getBufferMapper返回的是GraphicBufferMappercpp view plain copy 在CODE上查看代码片派生到我的代码片status_t GraphicBuffer:lockAsync(uint32_t inUsage, const Rect& rect, void* vaddr, int fenceFd) if (rect.left width | rect.top height) ALOGE(locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d), rect.left, rect.top, rect.right, rect.bottom, width, height); return BAD_VALUE; status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr, fenceFd); return res; 这里的GraphicBufferMapper:lockAsync调用的是mAllocMod的lock函数cpp view plain copy 在CODE上查看代码片派生到我的代码片status_t GraphicBufferMapper:lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void* vaddr, int fenceFd) ATRACE_CALL(); status_t err; if (mAllocMod-common.module_api_version = GRALLOC_MODULE_API_VERSION_0_3) err = mAllocMod-lockAsync(mAllocMod, handle, static_cast(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr, fenceFd); else if (fenceFd = 0) sync_wait(fenceFd, -1); close(fenceFd); err = mAllocMod-lock(mAllocMod, handle, static_cast(usage), bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); ALOGW_IF(err, lockAsync(.) failed %d (%s), err, strerror(-err); return err; mAllocMod也是Gralloc模块。cpp view plain copy 在CODE上查看代码片派生到我的代码片GraphicBufferMapper:GraphicBufferMapper() : mAllocMod(0) hw_module_t const* module; int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); ALOGE_IF(err, FATAL: cant find the %s module, GRALLOC_HARDWARE_MODULE_ID); if (err = 0) mAllocMod = reinterpret_cast(module); 最后我们来看下Gralloc模块的lock函数,其实也就是将handle的base(buffer地址)放到vaddr中。cpp view plain copy 在CODE上查看代码片派生到我的代码片static 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) flags & private_handle_t:PRIV_FLAGS_USES_UMP | hnd-flags & private_handle_t:PRIV_FLAGS_USES_ION) hnd-writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK; if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK) *vaddr = (void*)hnd-base;/将handle的base(buffer地址)放到vaddr中 return 0; 1.3 Canvas的获取这样我们再回过头来看nativeLockCanvas函数,buffer也申请了,buffer地址也放到了Canvas的SkBitmap中了(意味着写到canvas,可以写到buffer的地址中了)。最后我们再来看Canvas的获取。在nativeLockCanvas中通过GraphicsJNI:getNativeCanvas来获取到canvasObj,这个就是上层在ViewRootImpl的Canvas的对象。cpp view plain copy 在CODE上查看代码片派生到我的代码片Canvas* nativeCanvas = GraphicsJNI:getNativeCanvas(env, canvasObj); 我们来看下这个函数,这个就是获取Java层。cpp view plain copy 在CODE上查看代码片派生到我的代码片android:Canvas* GraphicsJNI:getNativeCanvas(JNIEnv* env, jobject canvas) SkASSERT(env); SkASSERT(canvas); SkASSERT(env-IsInstanceOf(canvas, gCanvas_class); jlong canvasHandle = env-GetLongField(canvas, gCanvas_nativeInstanceID); if (!canvasHandle) return NULL; return reinterpret_cast(canvasHandle); 最后通过如下没我们发现是Canvas的mNativeCanvasWrapper对象。cpp view plain copy 在CODE上查看代码片派生到我的代码片gCanvas_class = make_globalref(env, android/graphics/Canvas); gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, mNativeCanvasWrapper, J); 而在Canvas中如果是通过mNativeCanvasWrapper复制Canvas对象,使用如下构造函数。cpp view plain copy 在CODE上查看代码片派生到我的代码片public Canvas(long nativeCanvas) if (nativeCanvas = 0) throw new IllegalStateException(); mNativeCanvasWrapper = nativeCanvas; mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper); mDensity = Bitmap.getDefaultDensity(); 那么必然会有一个地方创建了Canvas对象,最后我们发现会在View中创建Canvas.cpp view plain copy 在CODE上查看代码片派生到我的代码片. Canvas canvas; if (attachInfo != null) canvas = attachInfo.mCanvas; if (canvas = null) canvas = new Canvas(); canvas.setBitmap(bitmap); . 最后都是通过SkBitmap来写数据到buffer中去。二、应用进程绘制绘制的话,我们举个简单的例子canvas.drawRectcpp view plain copy 在CODE上查看代码片派生到我的代码片public void drawRect(NonNull RectF rect, NonNull Paint paint) native_drawRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance(); 我们来看下native_drawRect函数cpp view plain copy 在CODE上查看代码片派生到我的代码片static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, jfloat right, jfloat bottom, jlong paintHandle) const Paint* paint = reinterpret_cast(paintHandle); get_canvas(canvasHandle)-drawRect(left, top, right, bottom, *paint); 最后是调用了SkiaCanvas的drawRectCoordscpp view plain copy 在CODE上查看代码片派生到我的代码片void SkiaCanvas:drawRect(float left, float top, float right, float bottom, const SkPaint& int) mCanvas-drawRectCoords(left, top, right, bottom, paint); SkCanvas的drawRectCoordscpp view plain copy 在CODE上查看代码片派生到我的代码片void SkCanvas:drawRectCoords(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, const SkPaint& paint) TRACE_EVENT0(disabled-by-default-skia, SkCanvas:drawRectCoords(); SkRect r; r.set(left, top, right, bottom); this-drawRect(r, paint); SkCanvas:DrawRect函数,这里的fDevice就是SkBitmap。cpp view plain copy 在CODE上查看代码片派生到我的代码片void SkCanvas:DrawRect(const SkDraw& draw, const SkPaint& paint, const SkRect& r, SkScalar textSize) if (paint.getStyle() = SkPaint:kFill_Style) draw.fDevice-drawRect(draw, r, paint); else SkPaint p(paint); p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth(); draw.fDevice-drawRect(draw, r, p); SkBitmap之前我们把buffer的地址传进去了,这样就可以将数据写入buffer了。三、绘制完成在ViewRootImpl中绘制完成后,最后会调用surface.unlockCanvasAndPost(canvas)cpp view plain copy 在CODE上查看代码片派生到我的代码片public void unlockCanvasAndPost(Canvas canvas) ed (mLock) checkNotReleasedLocked(); if (mHwuiContext != null) mHwuiContext.unlockAndPost(canvas); else unlockSwCanvasAndPost(canvas); 正常是调用unlockSwCanvasAndPost函数,这个函数主要是调用了nativeUnlockCanvasAndPost native函数。这里仙剑SkBitmap重新设置了一个空的,然后调用了surface的unlockAndPost函数cpp view plain copy 在CODE上查看代码片派生到我的代码片static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz, jlong nativeObject, jobjec

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论