void HTML::PaintScrollImage(Ogre::HardwarePixelBufferSharedPtr pixelBuffer, const Berkelium::Rect& scrollOrigRect, int scroll_dx, int scroll_dy) { Berkelium::Rect scrolledRect = scrollOrigRect.translate(scroll_dx, scroll_dy); Berkelium::Rect scrolled_shared_rect = scrollOrigRect.intersect(scrolledRect); // Only do scrolling if they have non-zero intersection if(scrolled_shared_rect.width() == 0 || scrolled_shared_rect.height() == 0) return; Berkelium::Rect shared_rect = scrolled_shared_rect.translate(-scroll_dx, -scroll_dy); size_t width = shared_rect.width(); size_t height = shared_rect.height(); Ogre::TexturePtr shadow = Ogre::TextureManager::getSingleton().createManual("scrollbuf", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, Ogre::Bitwise::firstPO2From(width), Ogre::Bitwise::firstPO2From(height), 1, 1, Ogre::PF_BYTE_BGRA); { Ogre::HardwarePixelBufferSharedPtr shadowBuffer = shadow->getBuffer(); Berkelium::Rect borderedScrollRect = GetBorderedRect(shared_rect); Berkelium::Rect borderedScrolledRect = GetBorderedRect(scrolled_shared_rect); shadowBuffer->blit(pixelBuffer, Ogre::Box(borderedScrollRect.left(), borderedScrollRect.top(), borderedScrollRect.right(), borderedScrollRect.bottom()), Ogre::Box(0, 0, width, height)); pixelBuffer->blit(shadowBuffer, Ogre::Box(0, 0, width, height), Ogre::Box(borderedScrolledRect.left(), borderedScrolledRect.top(), borderedScrolledRect.right(), borderedScrolledRect.bottom())); } Ogre::ResourcePtr shadowResource(shadow); Ogre::TextureManager::getSingleton().remove(shadowResource); }
void UnityBerkeliumWindow::onPaint(Berkelium::Window *win, const unsigned char *sourceBuffer, const Berkelium::Rect &sourceBufferRect, size_t numCopyRects, const Berkelium::Rect *copyRects, int dx, int dy, const Berkelium::Rect &scrollRect) { #ifdef DEBUG cerr << "[UnityBerkeliumWindow] onPaint called (window: " << win << ")" << endl; cerr << " sourceBuffer: " << (void *) sourceBuffer << endl; cerr << " sourceBufferRect: (left=" << sourceBufferRect.left() << ", width=" << sourceBufferRect.width() << ", top=" << sourceBufferRect.top() << ", height=" << sourceBufferRect.height() << ")" << endl; cerr << " num dirty rects: " << numCopyRects << endl; for(size_t i = 0; i < numCopyRects; ++i) cerr << " rect " << i << ": (left=" << copyRects[i].left() << ", width=" << copyRects[i].width() << ", top=" << copyRects[i].top() << ", height=" << copyRects[i].height() << ")" << endl; #endif //! @todo Handle Scrolling if(dx != 0 || dy != 0) { } // Apply the dirty rectangles for(size_t i = 0; i < numCopyRects; ++i) { convertColors(copyRects[i], sourceBuffer); m_lastDirtyRect = copyRects[i]; if(m_setPixelsFunc) m_setPixelsFunc(/*rect.left(), rect.top(), rect.width(), rect.height()*/); } // Call the paint callback if(m_applyTextureFunc) m_applyTextureFunc(); }
virtual void onPaint ( Berkelium::Window* wini, const unsigned char *bitmap_in, const Berkelium::Rect &bitmap_rect, size_t num_copy_rects, const Berkelium::Rect* copy_rects, int dx, int dy, const Berkelium::Rect& scroll_rect ) { if (!tex || (tex->GetFlags() & r3dTexture::fCreated) == 0 || !d_show_browser->GetBool()) return; void * dstBuf = tex->Lock(true); if (dstBuf) { ScrollSubrect(dstBuf, scroll_rect, dx, dy); for (size_t i = 0; i < num_copy_rects; ++i) { // Calc bitmap_rect relative coordinates int height = copy_rects[i].height(); int width = copy_rects[i].width(); int left = copy_rects[i].left(); int top = copy_rects[i].top(); r3d_assert(bitmap_rect.left() <= left); r3d_assert(bitmap_rect.top() <= top); r3d_assert(bitmap_rect.width() >= width); r3d_assert(bitmap_rect.height() >= height); unsigned char *dstPtr = reinterpret_cast<byte*>(dstBuf) + left * pixelSize + top * tex->GetLockPitch(); const unsigned char *srcPtr = bitmap_in + (left - bitmap_rect.left()) * pixelSize + (top - bitmap_rect.top()) * bitmap_rect.width() * pixelSize; for (int j = 0; j < height; ++j) { memcpy(dstPtr, srcPtr, width * pixelSize); dstPtr += tex->GetLockPitch(); srcPtr += bitmap_rect.width() * pixelSize; } } } tex->Unlock(); }
void UnityBerkeliumWindow::convertColors(const Berkelium::Rect &rect, const unsigned char *sourceBuffer) { // Note: we convert from BGRA bytes to RGBA floats. RGB24 textures in Unity are still 32bit in memory. for(int x = rect.left(); x < rect.right(); ++x) { for(int y = rect.top(); y < rect.bottom(); ++y) { // We copy to the beginning of the buffer // (because we can't change the start address of the buffer we provide the Unity .SetPixels function int idx = (y - rect.top()) * rect.width() + (x - rect.left()); //int idx = y * rect.width() + x; m_buffer[idx * 4 + 0] = sourceBuffer[idx * 4 + 2] / 255.0f; // R m_buffer[idx * 4 + 1] = sourceBuffer[idx * 4 + 1] / 255.0f; // G m_buffer[idx * 4 + 2] = sourceBuffer[idx * 4 + 0] / 255.0f; // B if(m_transparency) m_buffer[idx * 4 + 3] = sourceBuffer[idx * 4 + 3] / 255.0f; // A } } }
void UnityBerkeliumWindow::convertColors(const Berkelium::Rect &rect, const unsigned char *sourceBuffer, const Berkelium::Rect &srcRect) { int top = rect.top() - srcRect.top(); int left = rect.left() - srcRect.left(); // Note: we convert from BGRA bytes to RGBA floats. RGB24 textures in Unity are still 32bit in memory. for(int x = 0; x < rect.width(); ++x) { for(int y = 0; y < rect.height(); ++y) { int idx = (rect.height() - (y + 1)) * rect.width() + x; int sourceIdx = left + (y + top) * srcRect.width() + x; m_buffer[idx * 4 + 0] = sourceBuffer[sourceIdx * 4 + 2] / 255.0f; // R m_buffer[idx * 4 + 1] = sourceBuffer[sourceIdx * 4 + 1] / 255.0f; // G m_buffer[idx * 4 + 2] = sourceBuffer[sourceIdx * 4 + 0] / 255.0f; // B if(m_transparency) m_buffer[idx * 4 + 3] = sourceBuffer[sourceIdx * 4 + 3] / 255.0f; // A } } }
void BrowserWindowImpl::onPaint( Berkelium::Window *win, const unsigned char *sourceBuffer, const Berkelium::Rect &sourceBufferRect, size_t numCopyRects, const Berkelium::Rect *copyRects, int dx, int dy, const Berkelium::Rect &scrollRect) { // std::cout<<"Paint:"<<std::endl; video::IHardwarePixelBuffer* surface= m_texture->getSurface(0); video::ColorConverter::convert32BitTo32Bit(sourceBuffer,m_flipped,math::vector2d(sourceBufferRect.width(),sourceBufferRect.height()),0,1,1); video::LockedPixelBox lockedBox( math::box3d(sourceBufferRect.left(),sourceBufferRect.top(),0, sourceBufferRect.right(),sourceBufferRect.bottom(),1),video::EPixel_X8R8G8B8,(void*)m_flipped); lockedBox.box.MinP.y=m_size.y-lockedBox.box.MinP.y; lockedBox.box.MaxP.y=m_size.y-lockedBox.box.MaxP.y; math::Swap(lockedBox.box.MinP.y,lockedBox.box.MaxP.y); if(m_refresh) { surface->blitFromMemory(lockedBox); m_refresh=false; return; } for(int i=0;i<numCopyRects;++i) { // std::cout << "\tRect: " << copyRects[i].width()<<" "<<copyRects[i].height()<< std::endl; math::box3d lockBox(copyRects[i].left(),copyRects[i].top(),0, copyRects[i].right(),copyRects[i].bottom(),1); lockBox.MinP.y=m_size.y-lockBox.MinP.y; lockBox.MaxP.y=m_size.y-lockBox.MaxP.y; math::Swap(lockBox.MinP.y,lockBox.MaxP.y); video::LockedPixelBox lb=lockedBox.getSubBox(lockBox); surface->blitFromMemory(lb); // const video::LockedPixelBox& lb= surface->lock(lockBox,video::IHardwareBuffer::ELO_Discard); // memcpy(lb.data,sourceBuffer,sourceBufferRect.width()*sourceBufferRect.height()*4 } }
void UnityBerkeliumWindow::onPaint(Berkelium::Window *win, const unsigned char *sourceBuffer, const Berkelium::Rect &sourceBufferRect, size_t numCopyRects, const Berkelium::Rect *copyRects, int dx, int dy, const Berkelium::Rect &scrollRect) { #ifdef DEBUG cerr << "[UnityBerkeliumWindow] onPaint called (window: " << win << ")" << endl; cerr << " sourceBuffer: " << (void *) sourceBuffer << endl; cerr << " sourceBufferRect: (left=" << sourceBufferRect.left() << ", width=" << sourceBufferRect.width() << ", top=" << sourceBufferRect.top() << ", height=" << sourceBufferRect.height() << ")" << endl; cerr << " num dirty rects: " << numCopyRects << endl; for(size_t i = 0; i < numCopyRects; ++i) cerr << " rect " << i << ": (left=" << copyRects[i].left() << ", width=" << copyRects[i].width() << ", top=" << copyRects[i].top() << ", height=" << copyRects[i].height() << ")" << endl; #endif // Handle Scrolling if(dx != 0 || dy != 0) { // scroll_rect contains the Rect we need to move // First we figure out where the the data is moved to by translating it Berkelium::Rect scrolled_rect = scrollRect.translate(-dx, -dy); // Next we figure out where they intersect, giving the scrolled // region Berkelium::Rect scrolled_shared_rect = scrollRect.intersect(scrolled_rect); // Only do scrolling if they have non-zero intersection if (scrolled_shared_rect.width() > 0 && scrolled_shared_rect.height() > 0) { // And the scroll is performed by moving shared_rect by (dx,dy) scrolled_shared_rect.mTop = m_height - scrolled_shared_rect.bottom(); dy = -dy; if(m_scrollRectFunc) m_scrollRectFunc(scrolled_shared_rect.left(), scrolled_shared_rect.top(), scrolled_shared_rect.width(), scrolled_shared_rect.height(), dx, dy); } } // Apply the dirty rectangles for(size_t i = 0; i < numCopyRects; ++i) { convertColors(copyRects[i], sourceBuffer, sourceBufferRect); m_lastDirtyRect = copyRects[i]; m_lastDirtyRect.mTop = m_height - m_lastDirtyRect.bottom(); if(m_setPixelsFunc) m_setPixelsFunc(/*rect.left(), rect.top(), rect.width(), rect.height()*/); } // Call the paint callback if(m_applyTextureFunc) m_applyTextureFunc(); }
void UnityBerkeliumWindow::onPaint(Berkelium::Window *pWindow, const unsigned char *sourceBuffer, const Berkelium::Rect &rect, int dx, int dy, const Berkelium::Rect &scrollRect) { #ifdef DEBUG cerr << "[UnityBerkeliumWindow] onPaint called (window: " << pWindow << ")" << endl; cerr << " rect: (left=" << rect.left() << ", width=" << rect.width() << ", top=" << rect.top() << ", height=" << rect.height() << ")" << endl; cerr << " sourceBuffer: " << (void *) sourceBuffer << endl; #endif // Scrolling if(dx != 0 || dy != 0) { #if 0 // scroll_rect contains the Rect we need to move // First we figure out where the the data is moved to by translating it //Berkelium::Rect scrolled_rect = scrollRect.translate(-dx, -dy); Berkelium::Rect scrolled_rect = scrollRect; scrolled_rect.mLeft -= dx; scrolled_rect.mTop -= dy; // Next we figure out where they intersect, giving the scrolled // region Berkelium::Rect scrolled_shared_rect = scrollRect.intersect(scrolled_rect); // Only do scrolling if they have non-zero intersection if(scrolled_shared_rect.width() > 0 && scrolled_shared_rect.height() > 0) { // And the scroll is performed by moving shared_rect by (dx,dy) //Berkelium::Rect shared_rect = scrolled_shared_rect.translate(dx, dy); Berkelium::Rect shared_rect = scrolled_shared_rect; shared_rect.mLeft += dx; shared_rect.mTop += dy; for(int y = scrolled_shared_rect.top(); y < shared_rect.bottom(); ++y) { ::memcpy( m_buffer + y * m_width * 4 /*+ scrolled_shared_rect.left() * 4*/, m_buffer + ((scrolled_shared_rect.top() + y) * m_width /*+ scrolled_shared_rect.left()*/) * 4, scrolled_shared_rect.width() * 4 ); } // Copy the data out of the texture /*size_t scrollBuffSize = scrolled_shared_rect.width() * scrolled_shared_rect.height() * 4; unsigned char *scrollBuffer = new unsigned char[scrollBuffSize]; for(int line = 0; line < scrolled_shared_rect.height(); ++line) { ::memcpy( scrollBuffer + line * scrolled_shared_rect.width() * 4, }*/ #if 0 glGetTexImage( GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, scroll_buffer ); // Annoyingly, OpenGL doesn't provide convenient primitives, so // we manually copy out the region to the beginning of the // buffer int wid = scrolled_shared_rect.width(); int hig = scrolled_shared_rect.height(); for(int jj = 0; jj < hig; jj++) { memcpy( scroll_buffer + (jj*wid * 4), scroll_buffer + ((scrolled_shared_rect.top()+jj)*dest_texture_width + scrolled_shared_rect.left()) * 4, wid*4 ); } // And finally, we push it back into the texture in the right // location glTexSubImage2D(GL_TEXTURE_2D, 0, shared_rect.left(), shared_rect.top(), shared_rect.width(), shared_rect.height(), GL_BGRA, GL_UNSIGNED_BYTE, scroll_buffer ); #endif } #endif } // Apply the dirty rectangle convertColors(rect, sourceBuffer); // Call the paint callback m_lastDirtyRect = rect; m_paintFunc(/*rect.left(), rect.top(), rect.width(), rect.height()*/); }
/** * @inheritDoc. */ inline Ogre::Box BrowserWindow::rectToBox(Berkelium::Rect rect) { return Ogre::Box(rect.left(), rect.top(), 0, rect.right(), rect.bottom(), 1); }
void ScrollSubrect(void *data, const Berkelium::Rect& scroll_rect, int dx, int dy) { if (!data || !tex) return; byte *byteData = reinterpret_cast<byte*>(data); Berkelium::Rect dstRect = scroll_rect.translate(dx, dy); // Y scroll if (dy != 0) { int lineOffset = dy < 0 ? 1 : -1; int srcLine = dy < 0 ? scroll_rect.top() : scroll_rect.bottom() - 1; int dstLine = dy < 0 ? dstRect.top() : dstRect.bottom() - 1; int i = 0; while (i < scroll_rect.height()) { if (srcLine >= scroll_rect.top() && dstLine >= scroll_rect.top() && srcLine < scroll_rect.bottom() && dstLine < scroll_rect.bottom()) { byte *srcMem = byteData + srcLine * tex->GetLockPitch() + scroll_rect.left() * pixelSize; byte *dstMem = byteData + dstLine * tex->GetLockPitch() + scroll_rect.left() * pixelSize; size_t bytesToCopy = scroll_rect.width() * pixelSize; #ifndef FINAL_BUILD // Paranoid memory overrun check r3d_assert(dstMem + bytesToCopy <= byteData + tex->GetHeight() * tex->GetLockPitch()); #endif memcpy_s(dstMem, bytesToCopy, srcMem, bytesToCopy); } ++i; srcLine += lineOffset; dstLine += lineOffset; } } // X Scroll if (dx != 0) { Berkelium::Rect r = scroll_rect.intersect(dstRect); size_t tmpBufSize = r.width() * pixelSize; byte *tmpBuf = reinterpret_cast<byte*>(_alloca(tmpBufSize)); int srcOffset = r3dTL::Clamp(scroll_rect.left() - dx, 0, scroll_rect.right()); for (int i = r.top(); i < r.bottom(); ++i) { byte *srcData = byteData + i * tex->GetLockPitch() + srcOffset * pixelSize; byte *dstData = byteData + i * tex->GetLockPitch() + r.left() * pixelSize; memcpy_s(tmpBuf, tmpBufSize, srcData, tmpBufSize); #ifndef FINAL_BUILD // Paranoid memory overrun check r3d_assert(dstData + tmpBufSize <= byteData + tex->GetHeight() * tex->GetLockPitch()); #endif memcpy_s(dstData, tmpBufSize, tmpBuf, tmpBufSize); } } }
/** Handles an onPaint call by mapping the results into an OpenGL texture. The * first parameters are the same as Berkelium::WindowDelegate::onPaint. The * additional parameters and return value are: * \param dest_texture - the OpenGL texture handle for the texture to render * the results into. * \param dest_texture_width - width of destination texture * \param dest_texture_height - height of destination texture * \param ignore_partial - if true, ignore any partial updates. This is useful * if you have loaded a new page, but updates for the old page have not * completed yet. * \param scroll_buffer - a temporary workspace used for scroll data. Must be * at least dest_texture_width * dest_texture_height * 4 bytes large. * \returns true if the texture was updated, false otherwiase */ bool ofxBerkelium::mapOnPaintToTexture( Berkelium::Window *wini, const unsigned char* bitmap_in, const Berkelium::Rect& bitmap_rect, size_t num_copy_rects, const Berkelium::Rect *copy_rects, int dx, int dy, const Berkelium::Rect& scroll_rect, bool ignore_partial) { glBindTexture(GL_TEXTURE_2D, web_texture); const int kBytesPerPixel = 4; // If we've reloaded the page and need a full update, ignore updates // until a full one comes in. This handles out of date updates due to // delays in event processing. if (ignore_partial) { if (bitmap_rect.left() != 0 || bitmap_rect.top() != 0 || bitmap_rect.right() != width || bitmap_rect.bottom() != height) { return false; } glTexImage2D(GL_TEXTURE_2D, 0, kBytesPerPixel, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, bitmap_in); ignore_partial = false; return true; } // Now, we first handle scrolling. We need to do this first since it // requires shifting existing data, some of which will be overwritten by // the regular dirty rect update. if (dx != 0 || dy != 0) { // scroll_rect contains the Rect we need to move // First we figure out where the the data is moved to by translating it Berkelium::Rect scrolled_rect = scroll_rect.translate(-dx, -dy); // Next we figure out where they intersect, giving the scrolled // region Berkelium::Rect scrolled_shared_rect = scroll_rect.intersect(scrolled_rect); // Only do scrolling if they have non-zero intersection if (scrolled_shared_rect.width() > 0 && scrolled_shared_rect.height() > 0) { // And the scroll is performed by moving shared_rect by (dx,dy) Berkelium::Rect shared_rect = scrolled_shared_rect.translate(dx, dy); int wid = scrolled_shared_rect.width(); int hig = scrolled_shared_rect.height(); if (DEBUG_PAINT) { std::cout << "Scroll rect: w=" << wid << ", h=" << hig << ", (" << scrolled_shared_rect.left() << "," << scrolled_shared_rect.top() << ") by (" << dx << "," << dy << ")" << std::endl; } int inc = 1; char *outputBuffer = scroll_buffer; // source data is offset by 1 line to prevent memcpy aliasing // In this case, it can happen if dy==0 and dx!=0. char *inputBuffer = scroll_buffer+(width*1*kBytesPerPixel); int jj = 0; if (dy > 0) { // Here, we need to shift the buffer around so that we start in the // extra row at the end, and then copy in reverse so that we // don't clobber source data before copying it. outputBuffer = scroll_buffer+( (scrolled_shared_rect.top()+hig+1)*width - hig*wid)*kBytesPerPixel; inputBuffer = scroll_buffer; inc = -1; jj = hig-1; } // Copy the data out of the texture glGetTexImage( GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, inputBuffer ); // Annoyingly, OpenGL doesn't provide convenient primitives, so // we manually copy out the region to the beginning of the // buffer for(; jj < hig && jj >= 0; jj+=inc) { memcpy( outputBuffer + (jj*wid) * kBytesPerPixel, //scroll_buffer + (jj*wid * kBytesPerPixel), inputBuffer + ( (scrolled_shared_rect.top()+jj)*width + scrolled_shared_rect.left()) * kBytesPerPixel, wid*kBytesPerPixel ); } // And finally, we push it back into the texture in the right // location glTexSubImage2D(GL_TEXTURE_2D, 0, shared_rect.left(), shared_rect.top(), shared_rect.width(), shared_rect.height(), GL_BGRA, GL_UNSIGNED_BYTE, outputBuffer ); } } if (DEBUG_PAINT) { std::cout << "Bitmap rect: w=" << bitmap_rect.width()<<", h="<<bitmap_rect.height() <<", ("<<bitmap_rect.top()<<","<<bitmap_rect.left() <<") tex size "<<width<<"x"<<height <<std::endl; } for (size_t i = 0; i < num_copy_rects; i++) { int wid = copy_rects[i].width(); int hig = copy_rects[i].height(); int top = copy_rects[i].top() - bitmap_rect.top(); int left = copy_rects[i].left() - bitmap_rect.left(); if (DEBUG_PAINT) { std::cout << "Copy rect: w=" << wid << ", h=" << hig << ", (" << top << "," << left << ")" << std::endl; } for(int jj = 0; jj < hig; jj++) { memcpy( scroll_buffer + jj*wid*kBytesPerPixel, bitmap_in + (left + (jj+top)*bitmap_rect.width())*kBytesPerPixel, wid*kBytesPerPixel ); } // Finally, we perform the main update, just copying the rect that is // marked as dirty but not from scrolled data. glTexSubImage2D(GL_TEXTURE_2D, 0, copy_rects[i].left(), copy_rects[i].top(), wid, hig, GL_BGRA, GL_UNSIGNED_BYTE, scroll_buffer ); } glBindTexture(GL_TEXTURE_2D, 0); return true; }
void browser::onPaint( Berkelium::Window* wini, const unsigned char* bitmap_in, const Berkelium::Rect& bitmap_rect, size_t num_copy_rects, const Berkelium::Rect* copy_rects, int dx, int dy, const Berkelium::Rect& scroll_rect ) { const int bytes_per_pixel = 4; #ifdef BROWSER_USE_EXCEPTIONS try #endif { browser_instance& w = *instances.at( wini ); glBindTexture( GL_TEXTURE_2D, w.browser_texture ); if( w.full_refresh ) { if( bitmap_rect.left() != 0 || bitmap_rect.top() != 0 || bitmap_rect.right() != w.screen.x || bitmap_rect.bottom() != w.screen.y ) { return; } else { glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, w.screen.x, w.screen.y, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)bitmap_in ); w.full_refresh = false; return; } } if( dx != 0 || dy != 0 ) { Berkelium::Rect scrolled_rect = scroll_rect.translate( -dx, -dy ); Berkelium::Rect scrolled_shared_rect = scroll_rect.intersect( scrolled_rect ); if( scrolled_shared_rect.width() > 0 && scrolled_shared_rect.height() > 0 ) { Berkelium::Rect shared_rect = scrolled_shared_rect.translate( dx, dy ); int wid = scrolled_shared_rect.width(); int hig = scrolled_shared_rect.height(); int inc = 1; char* output_buffer = w.scroll_buffer; char* input_buffer = w.scroll_buffer + ( w.screen.x * 1 * bytes_per_pixel ); int jj = 0; if( dy > 0 ) { output_buffer = w.scroll_buffer + ( ( scrolled_shared_rect.top() + hig + 1 ) * w.screen.x - hig * wid ) * bytes_per_pixel; input_buffer = w.scroll_buffer; inc = -1; jj = hig - 1; } glGetTexImage( GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, input_buffer ); for( ; jj < hig && jj >= 0; jj += inc ) { memcpy( output_buffer + ( jj * wid ) * bytes_per_pixel, input_buffer + ( ( scrolled_shared_rect.top() + jj ) * w.screen.x + scrolled_shared_rect.left() ) * bytes_per_pixel, wid * bytes_per_pixel ); } glTexSubImage2D( GL_TEXTURE_2D, 0, shared_rect.left(), shared_rect.top(), shared_rect.width(), shared_rect.height(), GL_BGRA, GL_UNSIGNED_BYTE, output_buffer ); } } for( size_t i = 0; i < num_copy_rects; i++ ) { int wid = copy_rects[i].width(); int hig = copy_rects[i].height(); int top = copy_rects[i].top() - bitmap_rect.top(); int left = copy_rects[i].left() - bitmap_rect.left(); for( int jj = 0; jj < hig; jj++ ) { memcpy( w.scroll_buffer + jj * wid * bytes_per_pixel, bitmap_in + ( left + ( jj + top ) * bitmap_rect.width() ) * bytes_per_pixel, wid * bytes_per_pixel ); } glTexSubImage2D( GL_TEXTURE_2D, 0, copy_rects[i].left(), copy_rects[i].top(), wid, hig, GL_BGRA, GL_UNSIGNED_BYTE, w.scroll_buffer ); } w.full_refresh = false; } #ifdef BROWSER_USE_EXCEPTIONS catch( ... ) { } #endif }