Plane * CMRouter::initPlane(bool rotate90) { Tile * bufferTile = TiAlloc(); TiSetType(bufferTile, Tile::BUFFER); TiSetBody(bufferTile, NULL); QRectF bufferRect(rotate90 ? m_maxRect90 : m_maxRect); TileRect br; qrectToTile(bufferRect, br); bufferRect.adjust(-bufferRect.width(), -bufferRect.height(), bufferRect.width(), bufferRect.height()); //DebugDialog::debug("max rect", m_maxRect); //DebugDialog::debug("max rect 90", m_maxRect90); int l = fasterRealToTile(bufferRect.left()); int t = fasterRealToTile(bufferRect.top()); int r = fasterRealToTile(bufferRect.right()); int b = fasterRealToTile(bufferRect.bottom()); SETLEFT(bufferTile, l); SETYMIN(bufferTile, t); // TILE is Math Y-axis not computer-graphic Y-axis Plane * thePlane = TiNewPlane(bufferTile, br.xmini, br.ymini, br.xmaxi, br.ymaxi); SETRIGHT(bufferTile, r); SETYMAX(bufferTile, b); // TILE is Math Y-axis not computer-graphic Y-axis // do not use InsertTile here TiInsertTile(thePlane, &thePlane->maxRect, NULL, Tile::SPACE); //infoTileRect("insert", thePlane->maxRect); return thePlane; }
/** * Sets hwc layer rectangles required for hwc composition * * @param aVisible Input. Layer's unclipped visible rectangle * The origin is the layer's buffer * @param aTransform Input. Layer's transformation matrix * It transforms from layer space to screen space * @param aClip Input. A clipping rectangle. * The origin is the top-left corner of the screen * @param aBufferRect Input. The layer's buffer bounds * The origin is the buffer itself and hence always (0,0) * @param aSurceCrop Output. Area of the source to consider, * the origin is the top-left corner of the buffer * @param aVisibleRegionScreen Output. Visible region in screen space. * The origin is the top-left corner of the screen * @return true if the layer should be rendered. * false if the layer can be skipped */ static bool PrepareLayerRects(nsIntRect aVisible, const gfxMatrix& aTransform, nsIntRect aClip, nsIntRect aBufferRect, hwc_rect_t* aSourceCrop, hwc_rect_t* aVisibleRegionScreen) { gfxRect visibleRect(aVisible); gfxRect clip(aClip); gfxRect visibleRectScreen = aTransform.TransformBounds(visibleRect); // |clip| is guaranteed to be integer visibleRectScreen.IntersectRect(visibleRectScreen, clip); if (visibleRectScreen.IsEmpty()) { LOGD("Skip layer"); return false; } gfxMatrix inverse(aTransform); inverse.Invert(); gfxRect crop = inverse.TransformBounds(visibleRectScreen); // Map to buffer space crop -= visibleRect.TopLeft(); gfxRect bufferRect(aBufferRect); //clip to buffer size crop.IntersectRect(crop, aBufferRect); crop.RoundOut(); if (crop.IsEmpty()) { LOGD("Skip layer"); return false; } //propagate buffer clipping back to visible rect visibleRectScreen = aTransform.TransformBounds(crop + visibleRect.TopLeft()); visibleRectScreen.RoundOut(); aSourceCrop->left = crop.x; aSourceCrop->top = crop.y; aSourceCrop->right = crop.x + crop.width; aSourceCrop->bottom = crop.y + crop.height; aVisibleRegionScreen->left = visibleRectScreen.x; aVisibleRegionScreen->top = visibleRectScreen.y; aVisibleRegionScreen->right = visibleRectScreen.x + visibleRectScreen.width; aVisibleRegionScreen->bottom = visibleRectScreen.y + visibleRectScreen.height; return true; }
void wxImageBox::OnPaint(wxPaintEvent &event) { wxRect paintRect = getPaintRect(); if (paintRect.GetRight() >= m_imageWidth) paintRect.width = m_imageWidth - paintRect.x; if (paintRect.GetBottom() >= m_imageHeight) paintRect.height = m_imageHeight - paintRect.y; wxRect bufferRect(m_bufferX, m_bufferY, m_buffer->GetWidth(), m_buffer->GetHeight()); if (m_repaint || paintRect.x < bufferRect.x || paintRect.y < bufferRect.y || paintRect.GetRight() > bufferRect.GetRight() || paintRect.GetBottom() > bufferRect.GetBottom()) { Paint(); // update buffer m_repaint = false; //wxLogMessage("Repaint: %d,%d - %d,%d -> %d,%d - %d,%d", // paintRect.x, paintRect.y, paintRect.width, paintRect.height, // bufferRect.x, bufferRect.y, bufferRect.width, bufferRect.height); } wxPaintBox::OnPaint(event); }
status_t GonkBufferQueueProducer::queueBuffer(int slot, const QueueBufferInput &input, QueueBufferOutput *output) { ATRACE_CALL(); int64_t timestamp; bool isAutoTimestamp; Rect crop; int scalingMode; uint32_t transform; uint32_t stickyTransform; bool async; sp<Fence> fence; input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform, &async, &fence, &stickyTransform); if (fence == NULL) { ALOGE("queueBuffer: fence is NULL"); // Temporary workaround for b/17946343: soldier-on instead of returning an error. This // prevents the client from dying, at the risk of visible corruption due to hwcomposer // reading the buffer before the producer is done rendering it. Unless the buffer is the // last frame of an animation, the corruption will be transient. fence = Fence::NO_FENCE; // return BAD_VALUE; } switch (scalingMode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: break; default: ALOGE("queueBuffer: unknown scaling mode %d", scalingMode); return BAD_VALUE; } sp<IConsumerListener> listener; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); if (mCore->mIsAbandoned) { ALOGE("queueBuffer: GonkBufferQueue has been abandoned"); return NO_INIT; } const int maxBufferCount = mCore->getMaxBufferCountLocked(async); if (async && mCore->mOverrideMaxBufferCount) { // FIXME: Some drivers are manually setting the buffer count // (which they shouldn't), so we do this extra test here to // handle that case. This is TEMPORARY until we get this fixed. if (mCore->mOverrideMaxBufferCount < maxBufferCount) { ALOGE("queueBuffer: async mode is invalid with " "buffer count override"); return BAD_VALUE; } } if (slot < 0 || slot >= maxBufferCount) { ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot, maxBufferCount); return BAD_VALUE; } else if (mSlots[slot].mBufferState != GonkBufferSlot::DEQUEUED) { ALOGE("queueBuffer: slot %d is not owned by the producer " "(state = %d)", slot, mSlots[slot].mBufferState); return BAD_VALUE; } else if (!mSlots[slot].mRequestBufferCalled) { ALOGE("queueBuffer: slot %d was queued without requesting " "a buffer", slot); return BAD_VALUE; } ALOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " crop=[%d,%d,%d,%d] transform=%#x scale=%s", slot, mCore->mFrameCounter + 1, timestamp, crop.left, crop.top, crop.right, crop.bottom, transform, GonkBufferItem::scalingModeName(scalingMode)); const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); Rect croppedRect; crop.intersect(bufferRect, &croppedRect); if (croppedRect != crop) { ALOGE("queueBuffer: crop rect is not contained within the " "buffer in slot %d", slot); return BAD_VALUE; } mSlots[slot].mFence = fence; mSlots[slot].mBufferState = GonkBufferSlot::QUEUED; ++mCore->mFrameCounter; mSlots[slot].mFrameNumber = mCore->mFrameCounter; GonkBufferItem item; item.mAcquireCalled = mSlots[slot].mAcquireCalled; item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; item.mCrop = crop; item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; item.mTransformToDisplayInverse = bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY); item.mScalingMode = scalingMode; item.mTimestamp = timestamp; item.mIsAutoTimestamp = isAutoTimestamp; item.mFrameNumber = mCore->mFrameCounter; item.mSlot = slot; item.mFence = fence; item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async; mStickyTransform = stickyTransform; if (mCore->mQueue.empty()) { // When the queue is empty, we can ignore mDequeueBufferCannotBlock // and simply queue this buffer mCore->mQueue.push_back(item); listener = mCore->mConsumerListener; } else { // When the queue is not empty, we need to look at the front buffer // state to see if we need to replace it GonkBufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); if (front->mIsDroppable || !mSynchronousMode) { // If the front queued buffer is still being tracked, we first // mark it as freed if (mCore->stillTracking(front)) { mSlots[front->mSlot].mBufferState = GonkBufferSlot::FREE; // Reset the frame number of the freed buffer so that it is // the first in line to be dequeued again mSlots[front->mSlot].mFrameNumber = 0; } // Overwrite the droppable buffer with the incoming one *front = item; listener = mCore->mConsumerListener; } else { mCore->mQueue.push_back(item); listener = mCore->mConsumerListener; } } mCore->mBufferHasBeenQueued = true; mCore->mDequeueCondition.broadcast(); output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight, mCore->mTransformHint, mCore->mQueue.size()); } // Autolock scope // Call back without lock held if (listener != NULL) { listener->onFrameAvailable(); } return NO_ERROR; }
status_t BufferQueue::queueBuffer(int buf, const QueueBufferInput& input, QueueBufferOutput* output) { ATRACE_CALL(); ATRACE_BUFFER_INDEX(buf); Rect crop; uint32_t transform; int scalingMode; int64_t timestamp; input.deflate(×tamp, &crop, &scalingMode, &transform); ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " "scale=%s", buf, timestamp, crop.left, crop.top, crop.right, crop.bottom, transform, scalingModeName(scalingMode)); sp<ConsumerListener> listener; { // scope for the lock Mutex::Autolock lock(mMutex); if (mAbandoned) { ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } if (buf < 0 || buf >= mBufferCount) { ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d", mBufferCount, buf); return -EINVAL; } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { ST_LOGE("queueBuffer: slot %d is not owned by the client " "(state=%d)", buf, mSlots[buf].mBufferState); return -EINVAL; } else if (!mSlots[buf].mRequestBufferCalled) { ST_LOGE("queueBuffer: slot %d was enqueued without requesting a " "buffer", buf); return -EINVAL; } const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); Rect croppedCrop; crop.intersect(bufferRect, &croppedCrop); if (croppedCrop != crop) { ST_LOGE("queueBuffer: crop rect is not contained within the " "buffer in slot %d", buf); return -EINVAL; } if (mSynchronousMode) { // In synchronous mode we queue all buffers in a FIFO. mQueue.push_back(buf); // Synchronous mode always signals that an additional frame should // be consumed. listener = mConsumerListener; } else { // In asynchronous mode we only keep the most recent buffer. if (mQueue.empty()) { mQueue.push_back(buf); // Asynchronous mode only signals that a frame should be // consumed if no previous frame was pending. If a frame were // pending then the consumer would have already been notified. listener = mConsumerListener; } else { Fifo::iterator front(mQueue.begin()); // buffer currently queued is freed mSlots[*front].mBufferState = BufferSlot::FREE; // and we record the new buffer index in the queued list *front = buf; } } mSlots[buf].mTimestamp = timestamp; mSlots[buf].mCrop = crop; mSlots[buf].mTransform = transform; switch (scalingMode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: break; default: ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode); scalingMode = mSlots[buf].mScalingMode; break; } mSlots[buf].mBufferState = BufferSlot::QUEUED; mSlots[buf].mScalingMode = scalingMode; mFrameCounter++; mSlots[buf].mFrameNumber = mFrameCounter; mBufferHasBeenQueued = true; mDequeueCondition.broadcast(); output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size()); ATRACE_INT(mConsumerName.string(), mQueue.size()); } // scope for the lock // call back without lock held if (listener != 0) { listener->onFrameAvailable(); } return OK; }
bool ossimGeneralRasterWriter::writeToBsq() { ossimEndian endian; static const char* const MODULE = "ossimGeneralRasterWriter::writeToBsq"; if (traceDebug()) CLOG << " Entered." << std::endl; //*** // Get an arbitrary tile just to get the size in bytes! // This should be changed later... An ossimImageSource should know // this. //*** ossimRefPtr<ossimImageData> id; // Start the sequence at the first tile. theInputConnection->setToStartOfSequence(); ossim_uint64 bands = theInputConnection->getNumberOfOutputBands(); ossim_uint64 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); ossim_uint64 tilesHigh = theInputConnection->getNumberOfTilesVertical(); ossim_uint64 tileHeight = theInputConnection->getTileHeight(); ossim_uint64 numberOfTiles = theInputConnection->getNumberOfTiles(); ossim_uint64 width = theAreaOfInterest.width(); ossim_uint64 height = theAreaOfInterest.height(); ossim_uint64 bytesInLine = 0; ossim_uint64 buf_band_offset = 0; // Use the system "streampos" typedef for future 64 bit seeks (long long). streampos file_band_offset = 0; //*** // Buffer to hold one line x tileHeight //*** ossim_uint64 bufferSizeInBytes = 0; unsigned char* buffer = NULL; theMinPerBand.clear(); theMaxPerBand.clear(); ossim_uint64 tileNumber = 0; bool wroteSomethingOut = false; ossimScalarType scalarType = theInputConnection->getOutputScalarType(); for(ossim_uint64 i = 0; ((i < tilesHigh)&&(!needsAborting())); ++i) { if(buffer) { // Clear the buffer. memset(buffer, 0, bufferSizeInBytes); } ossimIrect bufferRect(theAreaOfInterest.ul().x, theAreaOfInterest.ul().y + i*tileHeight, theAreaOfInterest.ul().x + (width - 1), theAreaOfInterest.ul().y + i * tileHeight + (tileHeight - 1)); // Tile loop in the sample (width) direction. for(ossim_uint64 j = 0; ((j < tilesWide)&&(!needsAborting())); ++j) { // Get the tile and copy it to the buffer. id = theInputConnection->getNextTile(); if(id.valid()) { id->computeMinMaxPix(theMinPerBand, theMaxPerBand); if(!buffer) { bytesInLine = id->getScalarSizeInBytes() * width; buf_band_offset = bytesInLine * tileHeight; file_band_offset = height * bytesInLine; bufferSizeInBytes = bytesInLine * tileHeight * bands; buffer = new unsigned char[bufferSizeInBytes]; memset(buffer, 0, bufferSizeInBytes); } id->unloadTile(buffer, bufferRect, OSSIM_BSQ); } ++tileNumber; } // Get the number of lines to write from the buffer. ossim_uint64 linesToWrite = min(tileHeight, static_cast<ossim_uint64>(theAreaOfInterest.lr().y - bufferRect.ul().y + 1)); // Write the buffer out to disk. ossim_uint64 start_line = static_cast<ossim_uint64>(bufferRect.ul().y - theAreaOfInterest.ul().y); for (ossim_uint64 band = 0; ((band < bands)&&(!needsAborting())); ++band) { ossim_uint8* buf = buffer; buf += buf_band_offset * band; // Put the file pointer in the right spot. streampos pos = file_band_offset * band + start_line * bytesInLine; theOutputStream->seekp(pos, ios::beg); if (theOutputStream->fail()) { ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:" << "Error returned seeking to image data position!" << std::endl; setErrorStatus(); return false; } for (ossim_uint64 ii=0; ((ii<linesToWrite)&&(!needsAborting())); ++ii) { wroteSomethingOut = true; if(endian.getSystemEndianType() != theOutputByteOrder) { endian.swap(scalarType, buf, bytesInLine/ossim::scalarSizeInBytes(scalarType)); } theOutputStream->write((char*)buf, bytesInLine); if (theOutputStream->fail()) { ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:" << "Error returned writing line!" << std::endl; setErrorStatus(); return false; } buf += bytesInLine; } } // End of loop to write lines from buffer to tiff file. double tile = tileNumber; double numTiles = numberOfTiles; setPercentComplete(tile / numTiles * 100); if(needsAborting()) { setPercentComplete(100.0); } } // End of loop in the line (height) direction. // Free the memory. delete [] buffer; if (traceDebug()) CLOG << " Exited." << std::endl; return wroteSomethingOut; }
bool ossimGeneralRasterWriter::writeToBip() { ossimEndian endian; static const char* const MODULE = "ossimGeneralRasterWriter::writeToBip"; if (traceDebug()) CLOG << " Entered." << std::endl; //--- // Get an arbitrary tile just to get the size in bytes! // This should be changed later... An ossimImageSource should know // this. //--- ossimRefPtr<ossimImageData> id; // Start the sequence at the first tile. theInputConnection->setToStartOfSequence(); ossim_uint64 bands = theInputConnection->getNumberOfOutputBands(); ossim_uint64 tilesWide = theInputConnection->getNumberOfTilesHorizontal(); ossim_uint64 tilesHigh = theInputConnection->getNumberOfTilesVertical(); ossim_uint64 tileHeight = theInputConnection->getTileHeight(); ossim_uint64 numberOfTiles = theInputConnection->getNumberOfTiles(); ossim_uint64 width = theAreaOfInterest.width(); if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG) << "\nossimGeneralRasterWriter::writeToBip DEBUG:" << "\nbands: " << bands << "\ntilesWide: " << tilesWide << "\ntilesHigh: " << tilesHigh << "\ntileHeight: " << tileHeight << "\nnumberOfTiles: " << numberOfTiles << "\nwidth: " << width << std::endl; } //--- // Buffer to hold one line x tileHeight //--- ossim_uint64 bufferSizeInBytes = 0; ossim_uint64 bytesInLine = 0; unsigned char* buffer = NULL; theMinPerBand.clear(); theMaxPerBand.clear(); ossim_uint64 tileNumber = 0; bool wroteSomethingOut = false; ossimScalarType scalarType = theInputConnection->getOutputScalarType(); for(ossim_uint64 i = 0; ((i < tilesHigh)&&(!needsAborting())); ++i) { // Clear the buffer. if(buffer) { memset(buffer, 0, bufferSizeInBytes); } ossimIrect bufferRect(theAreaOfInterest.ul().x, theAreaOfInterest.ul().y + i*tileHeight, theAreaOfInterest.ul().x + (width - 1), theAreaOfInterest.ul().y + i*tileHeight + (tileHeight - 1)); // Tile loop in the sample (width) direction. for(ossim_uint64 j = 0; ((j < tilesWide)&&(!needsAborting())); ++j) { // Get the tile and copy it to the buffer. id = theInputConnection->getNextTile(); if(id.valid()) { id->computeMinMaxPix(theMinPerBand, theMaxPerBand); if(!buffer) { bytesInLine = id->getScalarSizeInBytes() * width * bands; //--- // Buffer to hold one line x tileHeight //--- bufferSizeInBytes = bytesInLine * tileHeight; buffer = new unsigned char[bufferSizeInBytes]; memset(buffer, 0, bufferSizeInBytes); } id->unloadTile(buffer, bufferRect, OSSIM_BIP); } ++tileNumber; } // Get the number of lines to write from the buffer. ossim_uint64 linesToWrite = min(tileHeight, static_cast<ossim_uint64>(theAreaOfInterest.lr().y - bufferRect.ul().y + 1)); // Write the buffer out to disk. ossim_uint8* buf = buffer; if(buf) { for (ossim_uint64 ii=0; ((ii<linesToWrite)&&(!needsAborting())); ++ii) { std::streamsize lineBytes = bytesInLine; wroteSomethingOut = true; if(endian.getSystemEndianType() != theOutputByteOrder) { endian.swap(scalarType, buf, lineBytes/ossim::scalarSizeInBytes(scalarType)); } theOutputStream->write((char*)buf, lineBytes); if (theOutputStream->fail()) { ossimNotify(ossimNotifyLevel_FATAL) << MODULE << " ERROR:" << "Error returned writing line!" << std::endl; setErrorStatus(); if(buffer) { // Free the memory. delete [] buffer; } return false; } buf += bytesInLine; } // End of loop to write lines from buffer to tiff file. } double tile = tileNumber; double numTiles = numberOfTiles; setPercentComplete(tile / numTiles * 100); if(needsAborting()) { setPercentComplete(100.0); } } // End of loop in the line (height) direction. if(buffer) { // Free the memory. delete [] buffer; } if (traceDebug()) CLOG << " Exited." << std::endl; return wroteSomethingOut; }