CanvasLayer::CanvasLayer(const CanvasLayer& layer) : LayerAndroid(layer) , m_canvas(0) , m_bitmap(0) { init(); if (!layer.m_canvas) { // The canvas has already been destroyed - this shouldn't happen ALOGW("Creating a CanvasLayer for a destroyed canvas!"); m_visibleContentRect = IntRect(); m_offsetFromRenderer = IntSize(); m_texture->setHwAccelerated(false); return; } // We are making a copy for the UI, sync the interesting bits m_visibleContentRect = layer.visibleContentRect(); m_offsetFromRenderer = layer.offsetFromRenderer(); bool previousState = m_texture->hasValidTexture(); if (!previousState && layer.m_dirtyCanvas.isEmpty()) { // We were previously in software and don't have anything new to draw, // so stay in software m_bitmap = layer.bitmap(); SkSafeRef(m_bitmap); } else { // Attempt to upload to a surface texture if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { // Blargh, no surface texture or ImageBuffer - fall back to software m_bitmap = layer.bitmap(); SkSafeRef(m_bitmap); // Merge the canvas invals with the layer's invals to repaint the needed // tiles. SkRegion::Iterator iter(layer.m_dirtyCanvas); const IntPoint& offset = m_visibleContentRect.location(); for (; !iter.done(); iter.next()) { SkIRect diff = iter.rect(); diff.fLeft += offset.x(); diff.fRight += offset.x(); diff.fTop += offset.y(); diff.fBottom += offset.y(); m_dirtyRegion.op(diff, SkRegion::kUnion_Op); } } if (previousState != m_texture->hasValidTexture()) { // Need to do a full inval of the canvas content as we are mode switching m_dirtyRegion.op(m_visibleContentRect.x(), m_visibleContentRect.y(), m_visibleContentRect.maxX(), m_visibleContentRect.maxY(), SkRegion::kUnion_Op); } } }
CanvasLayer::CanvasLayer(const CanvasLayer& layer) : LayerAndroid(layer) , m_canvas(0) , m_bitmap(0) , m_gpuCanvas(0) { init(); if (!layer.m_canvas) { // The canvas has already been destroyed - this shouldn't happen ALOGW("Creating a CanvasLayer for a destroyed canvas!"); m_visibleContentRect = IntRect(); m_offsetFromRenderer = IntSize(); m_texture->setHwAccelerated(false); return; } // We are making a copy for the UI, sync the interesting bits m_visibleContentRect = layer.visibleContentRect(); m_offsetFromRenderer = layer.offsetFromRenderer(); bool previousState = m_texture->hasValidTexture(); if(layer.m_canvas->isUsingGpuRendering()) return; ImageBuffer* imageBuffer = layer.m_canvas->buffer(); if (!previousState && layer.m_dirtyCanvas.isEmpty() && imageBuffer && !(imageBuffer->drawsUsingRecording())) { // We were previously in software and don't have anything new to draw, // so stay in software m_bitmap = layer.bitmap(); SkSafeRef(m_bitmap); } else { if(imageBuffer && imageBuffer->drawsUsingRecording() && !layer.m_canvas->isUsingGpuRendering()) { bool canUseGpuRendering = imageBuffer->canUseGpuRendering(); if(canUseGpuRendering && layer.m_canvas->canUseGpuRendering()) { layer.m_canvas->enableGpuRendering(); CanvasLayer::setGpuCanvasStatus(layer.uniqueId(), true); } } // If recording is being used if(imageBuffer && imageBuffer->drawsUsingRecording()) { GraphicsContext* gc = imageBuffer->context(); //SkPicture* canvasRecording = gc->platformContext()->getRecordingPicture(); SkPicture* canvasRecording = CanvasLayer::getRecordingPicture(this); SkBitmap* bitmap = CanvasLayer::getRecordingBitmap(this); SkCanvas* canvas = CanvasLayer::getRecordingCanvas(this); if(canvasRecording == NULL) return; if(bitmap == NULL || bitmap->width() != canvasRecording->width() || bitmap->height() != canvasRecording->height()) { SkBitmap* newBitmap = new SkBitmap(); newBitmap->setConfig(SkBitmap::kARGB_8888_Config, canvasRecording->width(), canvasRecording->height()); newBitmap->allocPixels(); newBitmap->eraseColor(0); CanvasLayer::setRecordingBitmap(newBitmap, this); bitmap = newBitmap; if(canvas != NULL) canvas->setBitmapDevice(*bitmap); } if(canvas == NULL) { canvas = new SkCanvas(); canvas->setBitmapDevice(*bitmap); CanvasLayer::setRecordingCanvas(canvas, this); } canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); canvasRecording->draw(canvas); if (!m_texture->uploadImageBitmap(bitmap)) { //SLOGD("+++++++++++++++++++++ Didn't upload bitmap .. fall back to software"); // TODO:: Fix this } } else { if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { // Blargh, no surface texture or ImageBuffer - fall back to software m_bitmap = layer.bitmap(); SkSafeRef(m_bitmap); // Merge the canvas invals with the layer's invals to repaint the needed // tiles. SkRegion::Iterator iter(layer.m_dirtyCanvas); const IntPoint& offset = m_visibleContentRect.location(); for (; !iter.done(); iter.next()) { SkIRect diff = iter.rect(); diff.fLeft += offset.x(); diff.fRight += offset.x(); diff.fTop += offset.y(); diff.fBottom += offset.y(); m_dirtyRegion.op(diff, SkRegion::kUnion_Op); } }else{ ImageBuffer* imageBuffer = layer.m_canvas->buffer(); bool recordingCanvasEnabled = layer.m_canvas->isRecordingCanvasEnabled(); if(recordingCanvasEnabled && imageBuffer && imageBuffer->isAnimating()){ SLOGD("[%s] Animation detected. Converting the HTML5 canvas buffer to a SkPicture.", __FUNCTION__); imageBuffer->convertToRecording(); } }//End of non-recording } if (previousState != m_texture->hasValidTexture()) { // Need to do a full inval of the canvas content as we are mode switching m_dirtyRegion.op(m_visibleContentRect.x(), m_visibleContentRect.y(), m_visibleContentRect.maxX(), m_visibleContentRect.maxY(), SkRegion::kUnion_Op); } } }