void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect) { IntRect dirtyRect(mapFromContents(contentsDirtyRect)); IntRect keepRectFitToTileSize = tileRectForCoordinate(tileCoordinateForPoint(m_keepRect.location())); keepRectFitToTileSize.unite(tileRectForCoordinate(tileCoordinateForPoint(innerBottomRight(m_keepRect)))); // Only iterate on the part of the rect that we know we might have tiles. IntRect coveredDirtyRect = intersection(dirtyRect, keepRectFitToTileSize); Tile::Coordinate topLeft = tileCoordinateForPoint(coveredDirtyRect.location()); Tile::Coordinate bottomRight = tileCoordinateForPoint(innerBottomRight(coveredDirtyRect)); for (int yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { for (int xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { RefPtr<Tile> currentTile = tileAt(Tile::Coordinate(xCoordinate, yCoordinate)); if (!currentTile) continue; // Pass the full rect to each tile as coveredDirtyRect might not // contain them completely and we don't want partial tile redraws. #if PLATFORM(JS) fprintf(stderr, "WebKit: TiledBackingStore: invalidate: invalidating currentTile (x,y,w,h): %i %i %i %i\n",dirtyRect.x(),dirtyRect.y(),dirtyRect.width(),dirtyRect.height()); #endif currentTile->invalidate(dirtyRect); } } startTileBufferUpdateTimer(); }
void TiledDrawingAreaProxy::invalidate(const IntRect& contentsDirtyRect) { IntRect dirtyRect(mapFromContents(contentsDirtyRect)); TiledDrawingAreaTile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft()); TiledDrawingAreaTile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight()); IntRect coverRect = calculateCoverRect(m_previousVisibleRect); Vector<TiledDrawingAreaTile::Coordinate> tilesToRemove; for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { RefPtr<TiledDrawingAreaTile> currentTile = tileAt(TiledDrawingAreaTile::Coordinate(xCoordinate, yCoordinate)); if (!currentTile) continue; if (!currentTile->rect().intersects(dirtyRect)) continue; // If a tile outside out current cover rect gets invalidated, just drop it instead of updating. if (!currentTile->rect().intersects(coverRect)) { tilesToRemove.append(currentTile->coordinate()); continue; } currentTile->invalidate(dirtyRect); } } unsigned removeCount = tilesToRemove.size(); for (unsigned n = 0; n < removeCount; ++n) removeTile(tilesToRemove[n]); startTileBufferUpdateTimer(); }
//--------------------------------------------------------------------- void TerrainLayerBlendMap::blit(const PixelBox &src, const Box &dstBox) { const PixelBox* srcBox = &src; if (srcBox->getWidth() != dstBox.getWidth() || srcBox->getHeight() != dstBox.getHeight()) { // we need to rescale src to dst size first (also confvert format) void* tmpData = OGRE_MALLOC(dstBox.getWidth() * dstBox.getHeight(), MEMCATEGORY_GENERAL); srcBox = OGRE_NEW PixelBox(dstBox.getWidth(), dstBox.getHeight(), 1, PF_L8, tmpData); Image::scale(src, *srcBox); } // pixel conversion PixelBox dstMemBox(dstBox, PF_L8, mData); PixelUtil::bulkPixelConversion(*srcBox, dstMemBox); if (srcBox != &src) { // free temp OGRE_FREE(srcBox->data, MEMCATEGORY_GENERAL); OGRE_DELETE srcBox; srcBox = 0; } Rect dRect(dstBox.left, dstBox.top, dstBox.right, dstBox.bottom); dirtyRect(dRect); }
void BrushToolEdit::drawColor(const QPoint &pt, Map &&map) { Terrain *tip = tool->tip(pt).data(); // compute affected rectangle QRect dirtyRect(pt, tip->size()); dirtyRect = dirtyRect.intersected(QRect(QPoint(0, 0), terrain->size())); if (!dirtyRect.isValid()) { return; } // get "before" terrain if (tool->before_ == nullptr || tool->before_->size() != tip->size()) { tool->before_ = QSharedPointer<Terrain>::create(tip->size()); } Terrain *before = tool->before_.data(); edit->copyBeforeTo(dirtyRect, terrain, before); edit->beginEdit(dirtyRect, terrain); for (int y = 0; y < dirtyRect.height(); ++y) { for (int x = 0; x < dirtyRect.width(); ++x) { int cx = x + dirtyRect.left(); int cy = y + dirtyRect.top(); int tx = cx - pt.x(); int ty = cy - pt.y(); map(terrain->color(cx, cy), before->color(x, y), tip->landform(tx, ty)); } } edit->endEdit(terrain); }
//--------------------------------------------------------------------- void TerrainLayerBlendMap::dirty() { Rect rect; rect.top = 0; rect.bottom = mBuffer->getHeight(); rect.left = 0; rect.right = mBuffer->getWidth(); dirtyRect(rect); }
void KisSimpleUpdateQueueTest::testChecksum() { QRect imageRect(0,0,512,512); QRect dirtyRect(100,100,100,100); const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), colorSpace, "test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisAdjustmentLayerSP adjustmentLayer = new KisAdjustmentLayer(image, "adj", 0, 0); image->lock(); image->addNode(paintLayer1, image->rootLayer()); image->addNode(adjustmentLayer, image->rootLayer()); image->unlock(); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); KisFilterConfiguration *configuration = filter->defaultConfiguration(0); KisTestableSimpleUpdateQueue queue; KisWalkersList& walkersList = queue.getWalkersList(); { TestUtil::LodOverride l(1, image); queue.addUpdateJob(adjustmentLayer, dirtyRect, imageRect, 1); QCOMPARE(walkersList[0]->checksumValid(), true); QCOMPARE(walkersList[0]->levelOfDetail(), 1); } adjustmentLayer->setFilter(configuration); { TestUtil::LodOverride l(1, image); QCOMPARE(walkersList[0]->checksumValid(), false); } QVector<KisUpdateJobItem*> jobs; KisTestableUpdaterContext context(2); { TestUtil::LodOverride l(1, image); queue.processQueue(context); } jobs = context.getJobs(); { TestUtil::LodOverride l(1, image); QCOMPARE(jobs[0]->walker()->checksumValid(), true); } }
void KisPrescaledProjectionTest::benchmarkUpdate() { QImage referenceImage(QString(FILES_DATA_DIR) + QDir::separator() + "lena.png"); QRect imageRect = QRect(QPoint(0,0), referenceImage.size()); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "projection test"); // set up 300dpi image->setResolution(300 / 72 , 300 / 72); KisPaintLayerSP layer = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, cs); layer->paintDevice()->convertFromQImage(referenceImage, 0); image->addNode(layer, image->rootLayer(), 0); KisPrescaledProjection projection; KisCoordinatesConverter converter; converter.setImage(image); projection.setCoordinatesConverter(&converter); projection.setMonitorProfile(0, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); projection.setImage(image); // Emulate "Use same aspect as pixels" converter.setResolution(image->xRes(), image->yRes()); converter.setZoom(1.0); KisUpdateInfoSP info = projection.updateCache(image->bounds()); projection.recalculateCache(info); QCOMPARE(imageRect, QRect(0,0,512,512)); QRect dirtyRect(0,0,20,20); const qint32 numShifts = 25; const QPoint offset(dirtyRect.width(),dirtyRect.height()); //CALLGRIND_START_INSTRUMENTATION; QBENCHMARK { for(qint32 i = 0; i < numShifts; i++) { KisUpdateInfoSP tempInfo = projection.updateCache(dirtyRect); projection.recalculateCache(tempInfo); dirtyRect.translate(offset); } } //CALLGRIND_STOP_INSTRUMENTATION; }
void Caret::render( GfxDevice * pDevice, Rect cell, const Rect& clip ) { if( m_ticks < m_cycleLength / 2 ) { Rect r = dirtyRect(cell); BlendMode oldMode = pDevice->blendMode(); pDevice->setBlendMode(BlendMode::Invert); pDevice->fill( Rect(r,clip), Color::White ); pDevice->setBlendMode(oldMode); } m_bNeedToRender = false; }
void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect) { IntRect dirtyRect(mapFromContents(contentsDirtyRect)); Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.location()); Tile::Coordinate bottomRight = tileCoordinateForPoint(innerBottomRight(dirtyRect)); for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { RefPtr<Tile> currentTile = tileAt(Tile::Coordinate(xCoordinate, yCoordinate)); if (!currentTile) continue; currentTile->invalidate(dirtyRect); } } startTileBufferUpdateTimer(); }
void PageWidgetDelegate::paint(Page* page, PageOverlayList* overlays, WebCanvas* canvas, const WebRect& rect, CanvasBackground background) { if (rect.isEmpty()) return; GraphicsContextBuilder builder(canvas); GraphicsContext& gc = builder.context(); gc.platformContext()->setDrawingToImageBuffer(background == Opaque ? false : true); gc.applyDeviceScaleFactor(page->deviceScaleFactor()); IntRect dirtyRect(rect); gc.save(); FrameView* view = mainFrameView(page); // FIXME: Can we remove the mainFrame()->document() check? if (view && page->mainFrame()->document()) { gc.clip(dirtyRect); view->paint(&gc, dirtyRect); if (overlays) overlays->paintWebFrame(gc); } else gc.fillRect(dirtyRect, Color::white, ColorSpaceDeviceRGB); gc.restore(); }
void Brush::applyLayerBrush(long int x, long int y, const Ogre::Vector3& position) { auto ter = m_group->getTerrain(x, y); if(!ter) return; auto indices = (position - ter->getPosition())/ter->getWorldSize(); indices += 0.5; auto cmd = dynamic_cast<undo::BlendmapEdit*>(m_currentCommand); assert(cmd != nullptr); cmd->monitorTerrain(x, y); size_t size = ter->getLayerBlendMapSize(); indices *= size; float brushSize = m_settings[m_mode].size/ter->getWorldSize() * size; float strength = m_settings[m_mode].strength * ((QApplication::queryKeyboardModifiers() & Qt::ShiftModifier)? -0.01f : 0.01f); auto layer = ter->getLayerBlendMap(cmd->getLayerIndex()); auto data = layer->getBlendPointer(); Ogre::Rect rect(Ogre::Math::Clamp<int>(indices.x-brushSize/2, 0, size), Ogre::Math::Clamp<int>(indices.z-brushSize/2, 0, size), Ogre::Math::Clamp<int>(indices.x+brushSize/2, 0, size), Ogre::Math::Clamp<int>(indices.z+brushSize/2, 0, size)); if(rect.bottom == rect.top || rect.left == rect.right) // brush does not reach this terrain return; for(int ix=rect.left; ix<rect.right; ix++) { for(int iy=rect.top; iy<rect.bottom; iy++) { float dist = std::sqrt(std::pow(ix-indices.x, 2) + std::pow(iy-indices.z, 2)); float distWeight = brushFunction(dist/brushSize*2, m_settings[m_mode].hardness); // std::cout << dist << " " << brushSize/2 << " " << distWeight << std::endl; data[iy*size+ix] += distWeight*strength; // data[iy*size+ix] -= 0.1; if(data[iy*size+ix] > 1.0) data[iy*size+ix] = 1.0; if(data[iy*size+ix] < 0.0) data[iy*size+ix] = 0.0; // std::cout << data[iy*size+ix] << " "; } } layer->dirtyRect(rect); layer->update(); }
void PageWidgetDelegate::paint(Page* page, PageOverlayList* overlays, WebCanvas* canvas, const WebRect& rect, CanvasBackground background) { if (rect.isEmpty()) return; GraphicsContext gc(canvas); gc.setCertainlyOpaque(background == Opaque); gc.applyDeviceScaleFactor(page->deviceScaleFactor()); gc.setUseHighResMarkers(page->deviceScaleFactor() > 1.5f); IntRect dirtyRect(rect); gc.save(); // Needed to save the canvas, not the GraphicsContext. FrameView* view = mainFrameView(page); // FIXME: Can we remove the mainFrame()->document() check? if (view && page->mainFrame()->document()) { gc.clip(dirtyRect); view->paint(&gc, dirtyRect); if (overlays) overlays->paintWebFrame(gc); } else { gc.fillRect(dirtyRect, Color::white); } gc.restore(); }
void PageWidgetDelegate::paint(Page& page, PageOverlayList* overlays, WebCanvas* canvas, const WebRect& rect, CanvasBackground background, LocalFrame& root) { if (rect.isEmpty()) return; GraphicsContext gc(canvas, nullptr); gc.setCertainlyOpaque(background == Opaque); float scaleFactor = page.deviceScaleFactor(); gc.scale(scaleFactor, scaleFactor); gc.setDeviceScaleFactor(scaleFactor); IntRect dirtyRect(rect); gc.save(); // Needed to save the canvas, not the GraphicsContext. FrameView* view = root.view(); if (view) { gc.clip(dirtyRect); view->paint(&gc, dirtyRect); if (overlays) overlays->paintWebFrame(gc); } else { gc.fillRect(dirtyRect, Color::white); } gc.restore(); }
void Brush::applyHeightBrush(long int x, long int y, const Ogre::Vector3& position, float average) { auto ter = m_group->getTerrain(x, y); if(!ter) return; auto indices = (position - ter->getPosition())/ter->getWorldSize(); indices += 0.5; auto cmd = dynamic_cast<undo::HeightmapEdit*>(m_currentCommand); assert(cmd != nullptr); indices.z = 1.0f - indices.z; indices *= ter->getSize(); float* heightdata = ter->getHeightData(); float brushSize = m_settings[m_mode].size/ter->getWorldSize() * ter->getSize(); size_t terSize = ter->getSize(); // LEFT TOP RIGHT BOTTOM Ogre::Rect rect(Ogre::Math::Clamp<int>(indices.x-brushSize/2, 0, terSize), // left Ogre::Math::Clamp<int>(indices.z-brushSize/2, 0, terSize), // top Ogre::Math::Clamp<int>(indices.x+brushSize/2, 0, terSize), // right Ogre::Math::Clamp<int>(indices.z+brushSize/2, 0, terSize)); // bottom std::cout << rect << std::endl; if(rect.bottom == rect.top || rect.left == rect.right) // brush does not reach this terrain return; cmd->monitorTerrain(x, y, rect); if(m_mode == M_HEIGHT_RAISE) { float strength = m_settings[m_mode].strength * ((QApplication::queryKeyboardModifiers() & Qt::ShiftModifier)? -0.1f : 0.1f); for(int ix=rect.left; ix<rect.right; ix++) { for(int iy=rect.top; iy<rect.bottom; iy++) { float dist = std::sqrt(std::pow(ix-indices.x, 2) + std::pow(iy-indices.z, 2)); heightdata[iy*terSize+ix] += brushFunction(dist/brushSize*2, m_settings[m_mode].hardness) * strength; } } } else if(m_mode == M_HEIGHT_SMOOTH) { for(int ix=rect.left; ix<rect.right; ix++) { for(int iy=rect.top; iy<rect.bottom; iy++) { float dist = std::sqrt(std::pow(ix-indices.x, 2) + std::pow(iy-indices.z, 2)); float weight = brushFunction(dist/brushSize*2, m_settings[m_mode].hardness); float difference = average - heightdata[iy*terSize+ix]; difference *= m_settings[m_mode].strength/10.0f; heightdata[iy*terSize+ix] += weight*difference; } } } else if(m_mode == M_HEIGHT_FLATTEN) { if(QApplication::queryKeyboardModifiers() & Qt::ShiftModifier) { m_height = position.y; m_drawer->setBrushOptions(m_settings[m_mode].size, m_settings[m_mode].hardness, m_height); } else { for(int ix=rect.left; ix<rect.right; ix++) { for(int iy=rect.top; iy<rect.bottom; iy++) { float dist = std::sqrt(std::pow(ix-indices.x, 2) + std::pow(iy-indices.z, 2)); float weight = brushFunction(dist/brushSize*2, m_settings[m_mode].hardness); float difference = m_height - heightdata[iy*terSize+ix]; difference *= m_settings[m_mode].strength/10.0f; heightdata[iy*terSize+ix] += weight*difference; } } } } ter->dirtyRect(rect); ter->updateGeometryWithoutNotifyNeighbours(); ter->update(); }
void didProcessTask() override { ASSERT_TRUE(m_isDirty); FloatRect dirtyRect(0, 0, 1, 1); m_imageBuffer->finalizeFrame(dirtyRect); ASSERT_FALSE(m_isDirty); }
//--------------------------------------------------------------------- void TerrainLayerBlendMap::setBlendValue(size_t x, size_t y, float val) { *(mData + y * mBuffer->getWidth() + x) = val; dirtyRect(Rect(x, y, x+1, y+1)); }
void BrushToolEdit::drawBlur(const QPoint &pt, float amount) { Terrain *tip = tool->tip(pt).data(); // compute affected rectangle QRect dirtyRect(pt, tip->size()); dirtyRect = dirtyRect.intersected(QRect(QPoint(0, 0), terrain->size())); if (!dirtyRect.isValid()) { return; } edit->beginEdit(dirtyRect, terrain); QSize tSize = terrain->size(); QSize tipSize = tip->size(); QSize blurBufferSize(dirtyRect.width() + 6, dirtyRect.height() + 6); TemporaryBuffer<__m128> blurBuffer1(blurBufferSize.width() * blurBufferSize.height(), 16); TemporaryBuffer<__m128> blurBuffer2(blurBufferSize.width() * blurBufferSize.height(), 16); TemporaryBuffer<float> tipBuffer(blurBufferSize.width() * blurBufferSize.height(), 4); for (int y = 0; y < blurBufferSize.height(); ++y) { int cy = y + dirtyRect.top() - 3; cy = std::max(std::min(cy, tSize.height() - 1), 0); for (int x = 0; x < blurBufferSize.width(); ++x) { int cx = x + dirtyRect.left() - 3; cx = std::max(std::min(cx, tSize.width() - 1), 0); quint32 color = terrain->color(cx, cy); auto colorMM = _mm_setr_epi32(color, 0, 0, 0); colorMM = _mm_unpacklo_epi8(colorMM, _mm_setzero_si128()); colorMM = _mm_unpacklo_epi16(colorMM, _mm_setzero_si128()); auto colorF = _mm_cvtepi32_ps(colorMM); _mm_store_ps(reinterpret_cast<float *>(blurBuffer1 + x + y * blurBufferSize.width()), colorF); } } for (int y = 0; y < blurBufferSize.height(); ++y) { int cy = y + dirtyRect.top() - 3; int ty = cy - pt.y(); if (ty >= 0 && ty < tipSize.height()) { for (int x = 0; x < blurBufferSize.width(); ++x) { int cx = x + dirtyRect.left() - 3; int tx = cx - pt.x(); tipBuffer[x + y * blurBufferSize.width()] = tx >= 0 && tx < tipSize.width() ? tip->landform(tx, ty) * amount : 0.f; } } else { std::fill(&tipBuffer[y * blurBufferSize.width()], &tipBuffer[(y + 1) * blurBufferSize.width()], 0.f); } } // apply horizontal blur for (int y = 0; y < blurBufferSize.height(); ++y) { __m128 *inBuf = blurBuffer1 + y * blurBufferSize.width(); __m128 *outBuf = blurBuffer2 + y * blurBufferSize.width(); float *varBuf = tipBuffer + y * blurBufferSize.width(); for (int x = 3; x < blurBufferSize.width() - 3; ++x) { float variance = varBuf[x]; __m128 kernel = globalGaussianKernelTable.fetch(variance); // sample input __m128 p1 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x)); p1 = _mm_add_ps(p1, p1); __m128 p2 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x + 1)); p2 = _mm_add_ps(p2, _mm_load_ps(reinterpret_cast<float *>(inBuf + x - 1))); __m128 p3 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x + 2)); p3 = _mm_add_ps(p3, _mm_load_ps(reinterpret_cast<float *>(inBuf + x - 2))); __m128 p4 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x + 3)); p4 = _mm_add_ps(p4, _mm_load_ps(reinterpret_cast<float *>(inBuf + x - 3))); // apply kernel p1 = _mm_mul_ps(p1, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(0, 0, 0, 0))); p2 = _mm_mul_ps(p2, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(1, 1, 1, 1))); p3 = _mm_mul_ps(p3, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(2, 2, 2, 2))); p4 = _mm_mul_ps(p4, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(3, 3, 3, 3))); p1 = _mm_add_ps(p1, p2); p3 = _mm_add_ps(p3, p4); auto p = _mm_add_ps(p1, p3); // store _mm_store_ps(reinterpret_cast<float *>(outBuf + x), p); } } // apply vertical blur for (int y = 3; y < blurBufferSize.height() - 3; ++y) { __m128 *inBuf = blurBuffer2 + y * blurBufferSize.width(); __m128 *outBuf = blurBuffer1 + y * blurBufferSize.width(); float *varBuf = tipBuffer + y * blurBufferSize.width(); for (int x = 3; x < blurBufferSize.width() - 3; x += 1) { // fetch kernel __m128 kernel = globalGaussianKernelTable.fetch(varBuf[x]); // load input __m128 p1 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x)); p1 = _mm_add_ps(p1, p1); __m128 p2 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x - blurBufferSize.width())); p2 = _mm_add_ps(p2, _mm_load_ps(reinterpret_cast<float *>(inBuf + x + blurBufferSize.width()))); __m128 p3 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x - blurBufferSize.width() * 2)); p3 = _mm_add_ps(p3, _mm_load_ps(reinterpret_cast<float *>(inBuf + x + blurBufferSize.width() * 2))); __m128 p4 = _mm_load_ps(reinterpret_cast<float *>(inBuf + x - blurBufferSize.width() * 3)); p4 = _mm_add_ps(p4, _mm_load_ps(reinterpret_cast<float *>(inBuf + x + blurBufferSize.width() * 3))); // apply kernel p1 = _mm_mul_ps(p1, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(0, 0, 0, 0))); p2 = _mm_mul_ps(p2, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(1, 1, 1, 1))); p3 = _mm_mul_ps(p3, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(2, 2, 2, 2))); p4 = _mm_mul_ps(p4, _mm_shuffle_ps(kernel, kernel, _MM_SHUFFLE(3, 3, 3, 3))); p1 = _mm_add_ps(p1, p2); p3 = _mm_add_ps(p3, p4); auto p = _mm_add_ps(p1, p3); // store _mm_store_ps(reinterpret_cast<float *>(outBuf + x), p); } } for (int y = 0; y < dirtyRect.height(); ++y) { __m128 *inBuf = blurBuffer1 + (y + 3) * blurBufferSize.width() + 3; for (int x = 0; x < dirtyRect.width(); ++x) { int cx = x + dirtyRect.left(); int cy = y + dirtyRect.top(); auto colorF = _mm_load_ps(reinterpret_cast<float *>(inBuf + x)); colorF = _mm_add_ps(colorF, _mm_set1_ps(0.5f)); colorF = _mm_add_ps(colorF, globalDitherSampler.getM128()); auto colorMM = _mm_cvttps_epi32(colorF); colorMM = _mm_packs_epi32(colorMM, colorMM); colorMM = _mm_packus_epi16(colorMM, colorMM); _mm_store_ss(reinterpret_cast<float*>(&terrain->color(cx, cy)), _mm_castsi128_ps(colorMM)); } } edit->endEdit(terrain); }
void BrushToolEdit::drawSmoothen(const QPoint &pt, float amount) { Terrain *tip = tool->tip(pt).data(); // compute affected rectangle QRect dirtyRect(pt, tip->size()); dirtyRect = dirtyRect.intersected(QRect(QPoint(0, 0), terrain->size())); if (!dirtyRect.isValid()) { return; } edit->beginEdit(dirtyRect, terrain); QSize tSize = terrain->size(); QSize tipSize = tip->size(); QSize blurBufferSize(dirtyRect.width() + 6, dirtyRect.height() + 6); TemporaryBuffer<float> blurBuffer1(blurBufferSize.width() * blurBufferSize.height(), 4); TemporaryBuffer<float> blurBuffer2(blurBufferSize.width() * blurBufferSize.height(), 4); TemporaryBuffer<float> tipBuffer(blurBufferSize.width() * blurBufferSize.height(), 4); for (int y = 0; y < blurBufferSize.height(); ++y) { int cy = y + dirtyRect.top() - 3; cy = std::max(std::min(cy, tSize.height() - 1), 0); for (int x = 0; x < blurBufferSize.width(); ++x) { int cx = x + dirtyRect.left() - 3; cx = std::max(std::min(cx, tSize.width() - 1), 0); blurBuffer1[x + y * blurBufferSize.width()] = terrain->landform(cx, cy); } } for (int y = 0; y < blurBufferSize.height(); ++y) { int cy = y + dirtyRect.top() - 3; int ty = cy - pt.y(); if (ty >= 0 && ty < tipSize.height()) { for (int x = 0; x < blurBufferSize.width(); ++x) { int cx = x + dirtyRect.left() - 3; int tx = cx - pt.x(); tipBuffer[x + y * blurBufferSize.width()] = tx >= 0 && tx < tipSize.width() ? tip->landform(tx, ty) * amount : 0.f; } } else { std::fill(&tipBuffer[y * blurBufferSize.width()], &tipBuffer[(y + 1) * blurBufferSize.width()], 0.f); } } // apply horizontal blur for (int y = 0; y < blurBufferSize.height(); ++y) { float *inBuf = blurBuffer1 + y * blurBufferSize.width(); float *outBuf = blurBuffer2 + y * blurBufferSize.width(); float *varBuf = tipBuffer + y * blurBufferSize.width(); for (int x = 3; x < blurBufferSize.width() - 3; ++x) { float variance = varBuf[x]; __m128 kernel = globalGaussianKernelTable.fetch(variance); // sample input __m128 p1 = _mm_loadu_ps(inBuf + x - 3); __m128 p2 = _mm_loadu_ps(inBuf + x); p1 = _mm_shuffle_ps(p1, p1, _MM_SHUFFLE(0, 1, 2, 3)); auto p = _mm_add_ps(p1, p2); // apply kernel p = _mm_mul_ps(p, kernel); p = _mm_hadd_ps(p, p); p = _mm_hadd_ps(p, p); // write _mm_store_ss(outBuf + x, p); } } // apply vertical blur for (int y = 3; y < blurBufferSize.height() - 3; ++y) { float *inBuf = blurBuffer2 + y * blurBufferSize.width(); float *outBuf = blurBuffer1 + y * blurBufferSize.width(); float *varBuf = tipBuffer + y * blurBufferSize.width(); for (int x = 0; x < blurBufferSize.width() - 3; x += 4) { // fetch kernel __m128 kernel1 = globalGaussianKernelTable.fetch(varBuf[x]); __m128 kernel2 = globalGaussianKernelTable.fetch(varBuf[x + 1]); __m128 kernel3 = globalGaussianKernelTable.fetch(varBuf[x + 2]); __m128 kernel4 = globalGaussianKernelTable.fetch(varBuf[x + 3]); _MM_TRANSPOSE4_PS(kernel1, kernel2, kernel3, kernel4); // load input __m128 p1 = _mm_loadu_ps(inBuf + x); p1 = _mm_add_ps(p1, p1); __m128 p2 = _mm_loadu_ps(inBuf + x - blurBufferSize.width()); p2 = _mm_add_ps(p2, _mm_loadu_ps(inBuf + x + blurBufferSize.width())); __m128 p3 = _mm_loadu_ps(inBuf + x - blurBufferSize.width() * 2); p3 = _mm_add_ps(p3, _mm_loadu_ps(inBuf + x + blurBufferSize.width() * 2)); __m128 p4 = _mm_loadu_ps(inBuf + x - blurBufferSize.width() * 3); p4 = _mm_add_ps(p4, _mm_loadu_ps(inBuf + x + blurBufferSize.width() * 3)); // apply kernel p1 = _mm_mul_ps(p1, kernel1); p2 = _mm_mul_ps(p2, kernel2); p3 = _mm_mul_ps(p3, kernel3); p4 = _mm_mul_ps(p4, kernel4); p1 = _mm_add_ps(p1, p2); p3 = _mm_add_ps(p3, p4); auto p = _mm_add_ps(p1, p3); // store _mm_storeu_ps(outBuf + x, p); } } for (int y = 0; y < dirtyRect.height(); ++y) { float *inBuf = blurBuffer1 + (y + 3) * blurBufferSize.width() + 3; for (int x = 0; x < dirtyRect.width(); ++x) { int cx = x + dirtyRect.left(); int cy = y + dirtyRect.top(); terrain->landform(cx, cy) = inBuf[x]; } } edit->endEdit(terrain); }
void ContentLayerChromium::updateContents() { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); if (!backing || backing->paintingGoesToWindow()) return; ASSERT(drawsContent()); ASSERT(layerRenderer()); // FIXME: Remove this test when tiled layers are implemented. m_skipsDraw = false; if (!layerRenderer()->checkTextureSize(m_bounds)) { m_skipsDraw = true; return; } void* pixels = 0; IntRect dirtyRect(m_dirtyRect); IntSize requiredTextureSize; IntSize bitmapSize; requiredTextureSize = m_bounds; IntRect boundsRect(IntPoint(0, 0), m_bounds); // If the texture needs to be reallocated then we must redraw the entire // contents of the layer. if (requiredTextureSize != m_allocatedTextureSize) dirtyRect = boundsRect; else { // Clip the dirtyRect to the size of the layer to avoid drawing outside // the bounds of the backing texture. dirtyRect.intersect(boundsRect); } #if PLATFORM(SKIA) const SkBitmap* skiaBitmap = 0; OwnPtr<skia::PlatformCanvas> canvas; OwnPtr<PlatformContextSkia> skiaContext; OwnPtr<GraphicsContext> graphicsContext; canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); skiaContext.set(new PlatformContextSkia(canvas.get())); // This is needed to get text to show up correctly. // FIXME: Does this take us down a very slow text rendering path? skiaContext->setDrawingToImageBuffer(true); graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); // Bring the canvas into the coordinate system of the paint rect. canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); skiaBitmap = &bitmap; ASSERT(skiaBitmap); SkAutoLockPixels lock(*skiaBitmap); SkBitmap::Config skiaConfig = skiaBitmap->config(); // FIXME: do we need to support more image configurations? if (skiaConfig == SkBitmap::kARGB_8888_Config) { pixels = skiaBitmap->getPixels(); bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); } #elif PLATFORM(CG) Vector<uint8_t> tempVector; int rowBytes = 4 * dirtyRect.width(); tempVector.resize(rowBytes * dirtyRect.height()); memset(tempVector.data(), 0, tempVector.size()); RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(), dirtyRect.width(), dirtyRect.height(), 8, rowBytes, colorSpace.get(), kCGImageAlphaPremultipliedLast)); CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height()); CGContextScaleCTM(contextCG.get(), 1, -1); GraphicsContext graphicsContext(contextCG.get()); // Translate the graphics context into the coordinate system of the dirty rect. graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y()); m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect); pixels = tempVector.data(); bitmapSize = dirtyRect.size(); #else #error "Need to implement for your platform." #endif unsigned textureId = m_contentsTexture; if (!textureId) textureId = layerRenderer()->createLayerTexture(); if (pixels) updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId); }