void LLViewerMediaImpl::update() { LLPluginClassMedia* plugin = getMediaPlugin(); if (!plugin) { return; } plugin->idle(); if (plugin->isPluginExited()) { destroyMediaSource(); return; } if (!plugin->textureValid()) { return; } if(mSuspendUpdates || !mVisible) { return; } LLViewerTexture* placeholder_image = updatePlaceholderImage(); if(placeholder_image) { LLRect dirty_rect; if (plugin->getDirty(&dirty_rect)) { // Constrain the dirty rect to be inside the texture S32 x_pos = llmax(dirty_rect.mLeft, 0); S32 y_pos = llmax(dirty_rect.mBottom, 0); S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; if(width > 0 && height > 0) { U8* data = plugin->getBitsData(); // Offset the pixels pointer to match x_pos and y_pos data += ( x_pos * plugin->getTextureDepth() * plugin->getBitsWidth() ); data += ( y_pos * plugin->getTextureDepth() ); placeholder_image->setSubImage( data, plugin->getBitsWidth(), plugin->getBitsHeight(), x_pos, y_pos, width, height, TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) } plugin->resetDirty(); } } }
/*LLViewerMediaTexture*/LLViewerTexture* LLViewerMediaImpl::updatePlaceholderImage() { if(mTextureId.isNull()) { // The code that created this instance will read from the plugin's bits. return NULL; } LLViewerMediaTexture* placeholder_image = (LLViewerMediaTexture*)LLViewerTextureManager::getFetchedTexture( mTextureId ); LLPluginClassMedia* plugin = getMediaPlugin(); placeholder_image->getLastReferencedTimer()->reset(); if (mNeedsNewTexture || placeholder_image->getUseMipMaps() || ! placeholder_image->mIsMediaTexture || (placeholder_image->getWidth() != plugin->getTextureWidth()) || (placeholder_image->getHeight() != plugin->getTextureHeight()) || (mTextureUsedWidth != plugin->getWidth()) || (mTextureUsedHeight != plugin->getHeight()) ) { llinfos << "initializing media placeholder" << llendl; llinfos << "movie image id " << mTextureId << llendl; int texture_width = plugin->getTextureWidth(); int texture_height = plugin->getTextureHeight(); int texture_depth = plugin->getTextureDepth(); // MEDIAOPT: check to see if size actually changed before doing work placeholder_image->destroyGLTexture(); // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? placeholder_image->reinit(FALSE); // probably not needed // MEDIAOPT: seems insane that we actually have to make an imageraw then // immediately discard it LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth); raw->clear(0x0f, 0x0f, 0x0f, 0xff); int discard_level = 0; // ask media source for correct GL image format constants placeholder_image->setExplicitFormat(plugin->getTextureFormatInternal(), plugin->getTextureFormatPrimary(), plugin->getTextureFormatType(), plugin->getTextureFormatSwapBytes()); placeholder_image->createGLTexture(discard_level, raw); // placeholder_image->setExplicitFormat() placeholder_image->setUseMipMaps(FALSE); // MEDIAOPT: set this dynamically on play/stop placeholder_image->mIsMediaTexture = true; mNeedsNewTexture = false; // If the amount of the texture being drawn by the media goes down in either width or height, // recreate the texture to avoid leaving parts of the old image behind. mTextureUsedWidth = plugin->getWidth(); mTextureUsedHeight = plugin->getHeight(); } return placeholder_image; }
void display() { mMediaSource->idle(); // Check whether the texture needs to be recreated. if(mMediaSource->textureValid()) { if( (mAppTextureWidth != mMediaSource->getTextureWidth() || mAppTextureHeight != mMediaSource->getTextureHeight()) && (mAppWindowWidth == mMediaSource->getWidth() && mAppWindowHeight == mMediaSource->getHeight()) ) { // Attempt to (re)create the texture createTexture(); } } // clear screen glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); if(mAppTexture != 0) { // use the browser texture glBindTexture( GL_TEXTURE_2D, mAppTexture ); // If dirty, update the texture. LLRect dirtyRect; if(!mMediaSource->textureValid()) { // LL_DEBUGS("media_plugin_test") << "Resize in progress, skipping update..." << LL_ENDL; } else if(mAppWindowWidth != mMediaSource->getWidth() || mAppWindowHeight != mMediaSource->getHeight()) { // A resize is in progress. Just wait for it... } else if(mMediaSource->getDirty(&dirtyRect)) { // grab the page const unsigned char* pixels = mMediaSource->getBitsData(); if ( pixels ) { // write them into the texture // Paranoia: intersect dirtyRect with (0, 0, mAppTextureWidth, mAppTextureHeight)? int x_offset = dirtyRect.mLeft; int y_offset = dirtyRect.mBottom; int width = dirtyRect.mRight - dirtyRect.mLeft; int height = dirtyRect.mTop - dirtyRect.mBottom; LL_DEBUGS("media_plugin_test") << "Updating, dirty rect is (" << dirtyRect.mLeft << ", " << dirtyRect.mTop << ", " << dirtyRect.mRight << ", " << dirtyRect.mBottom << "), update params are: (" << x_offset << ", " << y_offset << ", " << width << ", " << height << ")" << LL_ENDL; // Offset the pixels pointer properly pixels += (y_offset * mMediaSource->getTextureDepth() * mMediaSource->getTextureWidth()); pixels += (x_offset * mMediaSource->getTextureDepth()); glPixelStorei(GL_UNPACK_ROW_LENGTH, mMediaSource->getTextureWidth()); glTexSubImage2D( GL_TEXTURE_2D, 0, x_offset, y_offset, width, height, mMediaSource->getTextureFormatPrimary(), mMediaSource->getTextureFormatType(), pixels ); mMediaSource->resetDirty(); } } // scale the texture so that it fits the screen GLdouble media_texture_x = mAppWindowWidth / (double)mAppTextureWidth; GLdouble media_texture_y = mAppWindowHeight / (double)mAppTextureHeight; // draw the single quad full screen (orthographic) glEnable( GL_TEXTURE_2D ); glColor3f( 1.0f, 1.0f, 1.0f ); glBegin( GL_QUADS ); if(mAppTextureCoordsOpenGL) { // Render the texture as per opengl coords (where 0,0 is at the lower left) glTexCoord2d( 0, 0 ); glVertex2d( 0, 0 ); glTexCoord2d( 0 , media_texture_y ); glVertex2d( 0, mAppWindowHeight); glTexCoord2d( media_texture_x, media_texture_y ); glVertex2d( mAppWindowWidth , mAppWindowHeight); glTexCoord2d( media_texture_x, 0 ); glVertex2d( mAppWindowWidth, 0 ); } else { // Render the texture the "other way round" (where 0,0 is at the upper left) glTexCoord2d( 0, media_texture_y ); glVertex2d( 0, 0 ); glTexCoord2d( 0 , 0 ); glVertex2d( 0, mAppWindowHeight); glTexCoord2d( media_texture_x, 0 ); glVertex2d( mAppWindowWidth , mAppWindowHeight); glTexCoord2d( media_texture_x, media_texture_y ); glVertex2d( mAppWindowWidth, 0 ); } glEnd(); } glutSwapBuffers(); };