void MLAcceleratedImageFilter::addInputImage(GLuint id, const QByteArray &name) { if (_inTexInfos.size() >= MaxInImageCount) { qWarning() << Q_FUNC_INFO << ": too many input images"; return; } _inTexInfos << TextureInfo(id, name); }
TextureAtlas::TextureIndex TextureAtlas::AddTexture(const std::string& fname) { TextureList::iterator it = m_textureList.find(fname); if (it != m_textureList.end()) return it->second.texIdx; TextureIndex id = m_currentTextureIndex++; m_textureList.insert(std::make_pair(fname, TextureInfo((ILuint)-1, id))); return id; }
QSharedPointer<Texture> TextureManager::loadTexture(const QString &fileName, bool useDefaultTexture) { // сначала ищем текстуру в кэше TextureCache::iterator it = mTextureCache.find(fileName); if (it != mTextureCache.end()) { QSharedPointer<Texture> texture = it->mTexture.toStrongRef(); if (!texture.isNull()) return texture; mTextureCache.erase(it); } // не нашли в кэше - загружаем текстуру из файла QSharedPointer<Texture> texture; QString path = Project::getSingleton().getRootDirectory() + fileName; mPrimaryGLWidget->makeCurrent(); if (Utils::fileExists(path) && (texture = QSharedPointer<Texture>(new Texture(path)))->isLoaded()) { // добавляем файл на слежение if (!mWatcher->files().contains(path)) mWatcher->addPath(path); // добавляем текстуру в кэш mTextureCache.insert(fileName, TextureInfo(texture)); } else if (useDefaultTexture) { // возвращаем текстуру по умолчанию texture = QSharedPointer<Texture>(new Texture()); mTextureCache.insert(fileName, TextureInfo(texture)); } else { // очищаем указатель на текстуру в случае ошибки texture.clear(); } return texture; }
TextureSource::TextureSource(IrrlichtDevice *device): m_device(device) { assert(m_device); m_main_thread = get_current_thread_id(); // Add a NULL TextureInfo as the first index, named "" m_textureinfo_cache.push_back(TextureInfo("")); m_name_to_id[""] = 0; // Cache some settings // Note: Since this is only done once, the game must be restarted // for these settings to take effect m_setting_trilinear_filter = g_settings->getBool("trilinear_filter"); m_setting_bilinear_filter = g_settings->getBool("bilinear_filter"); m_setting_anisotropic_filter = g_settings->getBool("anisotropic_filter"); }
TextureInfo loadTexture(const std::string& filename, bool premultiply) { int width, height, comp; auto data = std::unique_ptr<unsigned char[], void(*)(void*)>( stbi_load((data_path + filename).c_str(), &width, &height, &comp, 4), &stbi_image_free); if (data == nullptr) return TextureInfo(); if (premultiply) { unsigned int size = width * height; for (unsigned int i = 0; i < size; ++i) { unsigned char alpha = data[i*4 + 3]; for (unsigned int j = 0; j < 3; ++j) { data[i*4 + j] = data[i*4 + j] * alpha / 255; } } } return loadTexture(width, height, data.get()); }
void DrawingBuffer::beginDestruction() { ASSERT(!m_destructionInProgress); m_destructionInProgress = true; clearPlatformLayer(); while (!m_recycledMailboxQueue.isEmpty()) deleteMailbox(m_recycledMailboxQueue.takeLast()); if (m_multisampleFBO) m_gl->DeleteFramebuffers(1, &m_multisampleFBO); if (m_fbo) m_gl->DeleteFramebuffers(1, &m_fbo); if (m_multisampleRenderbuffer) m_gl->DeleteRenderbuffers(1, &m_multisampleRenderbuffer); if (m_depthStencilBuffer) m_gl->DeleteRenderbuffers(1, &m_depthStencilBuffer); if (m_colorBuffer.textureId) { deleteChromiumImageForTexture(&m_colorBuffer); m_gl->DeleteTextures(1, &m_colorBuffer.textureId); } setSize(IntSize()); m_colorBuffer = TextureInfo(); m_frontColorBuffer = FrontBufferInfo(); m_multisampleRenderbuffer = 0; m_depthStencilBuffer = 0; m_multisampleFBO = 0; m_fbo = 0; if (m_layer) GraphicsLayer::unregisterContentsLayer(m_layer->layer()); }
void GLFramebuffer2D::Init() { TE_OGL(glGenFramebuffers(1, &m_handle_fb)); TE_OGL(glGenRenderbuffers(1, &m_handle_db)); auto params = TextureParameters(TextureFormat::RGBA, TextureFilterMode::LINEAR, TextureWrapMode::CLAMP, TextureDataType::UNSIGNED_BYTE, m_samples); m_texture.push_back(TextureInfo()); m_texture[0].texture = new GLTexture2D(m_width, m_height, nullptr, params); m_texture[0].attachment = TE_ATTACHMENT_0; TE_OGL(glBindRenderbuffer(GL_RENDERBUFFER, m_handle_db)); if (m_samples > 1) { TE_OGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_samples, GL_DEPTH_COMPONENT24, m_width, m_height)); } else { TE_OGL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_width, m_height)); } TE_OGL(glBindFramebuffer(GL_FRAMEBUFFER, m_handle_fb)); TE_OGL(glFramebufferTexture2D(GL_FRAMEBUFFER, AttachmentToGL(m_texture[0].attachment), m_samples > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, m_texture[0].texture->getHandle(), 0)); TE_OGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_handle_db)); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { std::cout << "Failed to create framebuffer properly!" << std::endl; } uint32 attachments[] = { GL_COLOR_ATTACHMENT0 }; TE_OGL(glDrawBuffers(1, attachments)); TE_OGL(glBindFramebuffer(GL_FRAMEBUFFER, 0)); TE_OGL(glBindRenderbuffer(GL_RENDERBUFFER, 0)); }
bool CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit, EditReplyVector& replyv) { switch (aEdit.type()) { case CompositableOperation::TOpCreatedTexture: { MOZ_LAYERS_LOG(("[ParentSide] Created texture")); const OpCreatedTexture& op = aEdit.get_OpCreatedTexture(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); compositable->EnsureDeprecatedTextureHost(op.textureId(), op.descriptor(), compositableParent->GetCompositableManager(), op.textureInfo()); break; } case CompositableOperation::TOpCreatedIncrementalTexture: { MOZ_LAYERS_LOG(("[ParentSide] Created texture")); const OpCreatedIncrementalTexture& op = aEdit.get_OpCreatedIncrementalTexture(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); compositable->EnsureDeprecatedTextureHostIncremental(compositableParent->GetCompositableManager(), op.textureInfo(), op.bufferRect()); break; } case CompositableOperation::TOpDestroyThebesBuffer: { MOZ_LAYERS_LOG(("[ParentSide] Created double buffer")); const OpDestroyThebesBuffer& op = aEdit.get_OpDestroyThebesBuffer(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositableHost = compositableParent->GetCompositableHost(); if (compositableHost->GetType() != BUFFER_CONTENT && compositableHost->GetType() != BUFFER_CONTENT_DIRECT) { return false; } DeprecatedContentHostBase* content = static_cast<DeprecatedContentHostBase*>(compositableHost); content->DestroyTextures(); break; } case CompositableOperation::TOpPaintTexture: { MOZ_LAYERS_LOG(("[ParentSide] Paint Texture X")); const OpPaintTexture& op = aEdit.get_OpPaintTexture(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); Layer* layer = compositable ? compositable->GetLayer() : nullptr; LayerComposite* shadowLayer = layer ? layer->AsLayerComposite() : nullptr; if (shadowLayer) { Compositor* compositor = static_cast<LayerManagerComposite*>(layer->Manager())->GetCompositor(); compositable->SetCompositor(compositor); compositable->SetLayer(layer); } else { // if we reach this branch, it most likely means that async textures // are coming in before we had time to attach the compositable to a // layer. Don't panic, it is okay in this case. it should not be // happening continuously, though. } if (layer) { RenderTraceInvalidateStart(layer, "FF00FF", layer->GetVisibleRegion().GetBounds()); } if (compositable) { const SurfaceDescriptor& descriptor = op.image(); compositable->EnsureDeprecatedTextureHost(op.textureId(), descriptor, compositableParent->GetCompositableManager(), TextureInfo()); MOZ_ASSERT(compositable->GetDeprecatedTextureHost()); SurfaceDescriptor newBack; bool shouldRecomposite = compositable->Update(descriptor, &newBack); if (IsSurfaceDescriptorValid(newBack)) { replyv.push_back(OpTextureSwap(compositableParent, nullptr, op.textureId(), newBack)); } if (IsAsync() && shouldRecomposite) { ScheduleComposition(op); } } if (layer) { RenderTraceInvalidateEnd(layer, "FF00FF"); } // return texure data to client if necessary ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); break; } case CompositableOperation::TOpPaintTextureRegion: { MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); Layer* layer = compositable->GetLayer(); if (!layer || layer->GetType() != Layer::TYPE_THEBES) { return false; } ThebesLayerComposite* thebes = static_cast<ThebesLayerComposite*>(layer); const ThebesBufferData& bufferData = op.bufferData(); RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds()); nsIntRegion frontUpdatedRegion; if (!compositable->UpdateThebes(bufferData, op.updatedRegion(), thebes->GetValidRegion(), &frontUpdatedRegion)) { return false; } replyv.push_back( OpContentBufferSwap(compositableParent, nullptr, frontUpdatedRegion)); RenderTraceInvalidateEnd(thebes, "FF00FF"); // return texure data to client if necessary ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); break; } case CompositableOperation::TOpPaintTextureIncremental: { MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); const OpPaintTextureIncremental& op = aEdit.get_OpPaintTextureIncremental(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); SurfaceDescriptor desc = op.image(); compositable->UpdateIncremental(op.textureId(), desc, op.updatedRegion(), op.bufferRect(), op.bufferRotation()); break; } case CompositableOperation::TOpUpdatePictureRect: { const OpUpdatePictureRect& op = aEdit.get_OpUpdatePictureRect(); CompositableHost* compositable = static_cast<CompositableParent*>(op.compositableParent())->GetCompositableHost(); MOZ_ASSERT(compositable); compositable->SetPictureRect(op.picture()); break; } case CompositableOperation::TOpUseTiledLayerBuffer: { MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer")); const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); TiledLayerComposer* tileComposer = compositable->AsTiledLayerComposer(); NS_ASSERTION(tileComposer, "compositable is not a tile composer"); const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor(); tileComposer->UseTiledLayerBuffer(this, tileDesc); break; } case CompositableOperation::TOpRemoveTexture: { const OpRemoveTexture& op = aEdit.get_OpRemoveTexture(); CompositableHost* compositable = AsCompositable(op); RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); MOZ_ASSERT(tex.get()); compositable->RemoveTextureHost(tex); // return texure data to client if necessary ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); break; } case CompositableOperation::TOpUseTexture: { const OpUseTexture& op = aEdit.get_OpUseTexture(); CompositableHost* compositable = AsCompositable(op); RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); MOZ_ASSERT(tex.get()); compositable->UseTextureHost(tex); if (IsAsync()) { ScheduleComposition(op); // Async layer updates don't trigger invalidation, manually tell the layer // that its content have changed. if (compositable->GetLayer()) { compositable->GetLayer()->SetInvalidRectToVisibleRegion(); } } // return texure data to client if necessary ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); break; } case CompositableOperation::TOpUseComponentAlphaTextures: { const OpUseComponentAlphaTextures& op = aEdit.get_OpUseComponentAlphaTextures(); CompositableHost* compositable = AsCompositable(op); RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent()); RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent()); MOZ_ASSERT(texOnBlack && texOnWhite); compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite); if (IsAsync()) { ScheduleComposition(op); } // return texure data to client if necessary ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); break; } case CompositableOperation::TOpUpdateTexture: { const OpUpdateTexture& op = aEdit.get_OpUpdateTexture(); RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent()); MOZ_ASSERT(texture); texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion ? &op.region().get_nsIntRegion() : nullptr); // no region means invalidate the entire surface break; } default: { MOZ_ASSERT(false, "bad type"); } } return true; }
void GLFramebuffer2D::addAttachment(Attachment attach) { m_texture.push_back(TextureInfo()); m_texture[m_texture.size() - 1].attachment = attach; resizeTexture(m_width, m_height); }
TextureInfo ImageClientSingle::GetTextureInfo() const { return TextureInfo(COMPOSITABLE_IMAGE); }
void TextureManager::CheckUpdate() { // The images or their lenses have changed. // Find what size we should have the textures. // Note that one image changing does affect the rest, if an image suddenly // takes up more space, the others should take up less. unsigned int num_images = m_pano->getNrOfImages(); if (num_images == 0) { textures.clear(); return; } // if we are doing photometric correction, and someone changed the output // exposure, all of our images are at the wrong exposure. if (photometric_correct && view_state->RequireRecalculatePhotometric()) { textures.clear(); } HuginBase::PanoramaOptions *dest_img = view_state->GetOptions(); // Recalculuate the ideal image density if required // TODO tidy up once it works. DEBUG_INFO("Updating texture sizes."); // find the total of fields of view of the images, in degrees squared // we assume each image has the same density across all it's pixels double total_fov = 0.0; for (unsigned int image_index = 0; image_index < num_images; image_index++) { HuginBase::SrcPanoImage *src = view_state->GetSrcImage(image_index); double aspect = double(src->getSize().height()) / double(src->getSize().width()); total_fov += src->getHFOV() * aspect; }; // now find the ideal density texel_density = double(GetMaxTotalTexels()) / total_fov; // now recalculate the best image sizes // The actual texture size is the biggest one possible withouth scaling the // image up in any direction. We only specifiy mipmap levels we can fit in // a given amount of texture memory, while respecting the image's FOV. int texels_used = 0; double ideal_texels_used = 0.0; for (unsigned int image_index = 0; image_index < num_images; image_index++) { // find this texture // if it has not been created before, it will be created now. std::map<TextureKey, TextureInfo>::iterator it; HuginBase::SrcPanoImage *img_p = view_state->GetSrcImage(image_index); TextureKey key(img_p, &photometric_correct); it = textures.find(key); TextureInfo *texinfo; /* This section would allow us to reuse textures generated when we want * to change the size. It is not used as it causes segmentation faults * under Ubuntu 8.04's "ati" graphics driver. */ #if 0 if (it == textures.end()) { // We haven't seen this image before. // Find a size for it and make its texture. // store the power that 2 is raised to, not the actual size unsigned int max_tex_width_p = int(log2(img_p->getSize().width())), max_tex_height_p = int(log2(img_p->getSize().height())); // check this is hardware supported. { unsigned int biggest = GetMaxTextureSizePower(); if (biggest < max_tex_width_p) max_tex_width_p = biggest; if (biggest < max_tex_height_p) max_tex_height_p = biggest; } std::cout << "Texture size for image " << image_index << " is " << (1 << max_tex_width_p) << " by " << (1 << max_tex_height_p) << "\n"; // create a new texinfo and store the texture details. std::cout << "About to create new TextureInfo for " << img_p->getFilename() << ".\n"; std::pair<std::map<TextureKey, TextureInfo>::iterator, bool> ins; ins = textures.insert(std::pair<TextureKey, TextureInfo> (TextureKey(img_p, &photometric_correct), // the key is used to identify the image with (or without) // photometric correction parameters. TextureInfo(max_tex_width_p, max_tex_height_p) )); texinfo = &((ins.first)->second); } else { texinfo = &(it->second); } // find the highest mipmap we want to use. double hfov = img_p->getHFOV(), aspect = double (texinfo->height) / double (texinfo->width), ideal_texels = texel_density * hfov * aspect, // we would like a mipmap with this size: ideal_tex_width = sqrt(ideal_texels / aspect), ideal_tex_height = aspect * ideal_tex_width; // Ideally this mipmap would bring us up to this many texels ideal_texels_used += ideal_texels; std::cout << "Ideal mip size: " << ideal_tex_width << " by " << ideal_tex_height << "\n"; // Find the smallest mipmap level that is at least this size. int max_mip_level = (texinfo->width_p > texinfo->height_p) ? texinfo->width_p : texinfo->height_p; int mip_level = max_mip_level - ceil((ideal_tex_width > ideal_tex_height) ? log2(ideal_tex_width) : log2(ideal_tex_height)); // move to the next mipmap level if we are over budget. if ((texels_used + (1 << (texinfo->width_p + texinfo->height_p - mip_level * 2))) > ideal_texels_used) { // scale down mip_level ++; } // don't allow any mipmaps smaller than the 1 by 1 pixel one. if (mip_level > max_mip_level) mip_level = max_mip_level; // don't allow any mipmaps with a negative level of detail (scales up) if (mip_level < 0) mip_level = 0; // find the size of this level int mip_width_p = texinfo->width_p - mip_level, mip_height_p = texinfo->height_p - mip_level; // check if we have scaled down to a single line, and make sure we // limit the line's width to 1 pixel. if (mip_width_p < 0) mip_width_p = 0; if (mip_height_p < 0) mip_height_p = 0; // now count these texels as used- we are ignoring the smaller mip // levels, they add 1/3 on to the size. texels_used += 1 << (mip_width_p + mip_height_p); std::cout << "biggest mipmap of image " << image_index << " is " << (1 << mip_width_p) << " by " << (1 << mip_height_p) << " (level " << mip_level <<").\n"; std::cout << "Ideal texels used " << int(ideal_texels_used) << ", actually used " << texels_used << ".\n\n"; if (texinfo->min_lod != mip_level) { // maximum level required changed. if (texinfo->min_lod > mip_level) { // generate more levels texinfo->DefineLevels(mip_level, (texinfo->min_lod > max_mip_level) ? max_mip_level : texinfo->min_lod - 1, photometric_correct, dest_img, view_state->GetSrcImage(image_index)); } texinfo->SetMaxLevel(mip_level); texinfo->min_lod = mip_level; } } #endif /* Instead of the above section, replace the whole texture when appropriate: */ // Find a size for it double hfov = img_p->getHFOV(), aspect = double (img_p->getSize().height()) / double (img_p->getSize().width()), ideal_texels = texel_density * hfov * aspect, // we would like a texture this size: ideal_tex_width = sqrt(ideal_texels / aspect), ideal_tex_height = aspect * ideal_tex_width; // shrink if bigger than the original, avoids scaling up excessively. if (ideal_tex_width > img_p->getSize().width()) ideal_tex_width = img_p->getSize().width(); if (ideal_tex_height > img_p->getSize().height()) ideal_tex_height = img_p->getSize().height(); // we will need to round up/down to a power of two // round up first, then shrink if over budget. // store the power that 2 is raised to, not the actual size unsigned int tex_width_p = int(log2(ideal_tex_width)) + 1, tex_height_p = int(log2(ideal_tex_height)) + 1; // check this is hardware supported. { unsigned int biggest = GetMaxTextureSizePower(); if (biggest < tex_width_p) tex_width_p = biggest; if (biggest < tex_height_p) tex_height_p = biggest; } // check if this is over budget. ideal_texels_used += ideal_texels; // while the texture is over budget, shrink it while ( (texels_used + (1 << (tex_width_p + tex_height_p))) > ideal_texels_used) { // smaller aspect means the texture is wider. if ((double) (1 << tex_height_p) / (double) (1 << tex_width_p) < aspect) { tex_width_p--; } else { tex_height_p--; } } // we have a nice size texels_used += 1 << (tex_width_p + tex_height_p); if ( it == textures.end() || (it->second).width_p != tex_width_p || (it->second).height_p != tex_height_p) { // Either: 1. We haven't seen this image before // or: 2. Our texture for this is image is the wrong size // ...therefore we make a new one the right size: // // remove duplicate key if exists TextureKey checkKey (img_p, &photometric_correct); if (textures.find(checkKey) != textures.end()) { // Already exists in map, remove it first before adding a new one textures.erase(checkKey); } std::pair<std::map<TextureKey, TextureInfo>::iterator, bool> ins; ins = textures.insert(std::pair<TextureKey, TextureInfo> (TextureKey(img_p, &photometric_correct), // the key is used to identify the image with (or without) // photometric correction parameters. TextureInfo(view_state, tex_width_p, tex_height_p) )); // create and upload the texture image texinfo = &((ins.first)->second); texinfo->DefineLevels(0, // minimum mip level // maximum mip level tex_width_p > tex_height_p ? tex_width_p : tex_height_p, photometric_correct, *dest_img, *view_state->GetSrcImage(image_index)); texinfo->DefineMaskTexture(*view_state->GetSrcImage(image_index)); } else { if(view_state->RequireRecalculateMasks(image_index)) { //mask for this image has changed, also update only mask (*it).second.UpdateMask(*view_state->GetSrcImage(image_index)); }; } }
bool CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit, EditReplyVector& replyv) { switch (aEdit.type()) { case CompositableOperation::TOpCreatedTexture: { MOZ_LAYERS_LOG(("[ParentSide] Created texture")); const OpCreatedTexture& op = aEdit.get_OpCreatedTexture(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); compositable->EnsureTextureHost(op.textureId(), op.descriptor(), compositableParent->GetCompositableManager(), op.textureInfo()); break; } case CompositableOperation::TOpDestroyThebesBuffer: { MOZ_LAYERS_LOG(("[ParentSide] Created double buffer")); const OpDestroyThebesBuffer& op = aEdit.get_OpDestroyThebesBuffer(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); ContentHostBase* content = static_cast<ContentHostBase*>(compositableParent->GetCompositableHost()); content->DestroyTextures(); break; } case CompositableOperation::TOpPaintTexture: { MOZ_LAYERS_LOG(("[ParentSide] Paint Texture X")); const OpPaintTexture& op = aEdit.get_OpPaintTexture(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); Layer* layer = compositable ? compositable->GetLayer() : nullptr; LayerComposite* shadowLayer = layer ? layer->AsLayerComposite() : nullptr; if (shadowLayer) { Compositor* compositor = static_cast<LayerManagerComposite*>(layer->Manager())->GetCompositor(); compositable->SetCompositor(compositor); compositable->SetLayer(layer); } else { // if we reach this branch, it most likely means that async textures // are coming in before we had time to attach the conmpositable to a // layer. Don't panic, it is okay in this case. it should not be // happening continuously, though. } if (layer) { RenderTraceInvalidateStart(layer, "FF00FF", layer->GetVisibleRegion().GetBounds()); } if (compositable) { const SurfaceDescriptor& descriptor = op.image(); compositable->EnsureTextureHost(op.textureId(), descriptor, compositableParent->GetCompositableManager(), TextureInfo()); MOZ_ASSERT(compositable->GetTextureHost()); SurfaceDescriptor newBack; bool shouldRecomposite = compositable->Update(descriptor, &newBack); if (IsSurfaceDescriptorValid(newBack)) { replyv.push_back(OpTextureSwap(compositableParent, nullptr, op.textureId(), newBack)); } if (shouldRecomposite && compositableParent->GetCompositorID()) { CompositorParent* cp = CompositorParent::GetCompositor(compositableParent->GetCompositorID()); if (cp) { cp->ScheduleComposition(); } } } if (layer) { RenderTraceInvalidateEnd(layer, "FF00FF"); } break; } case CompositableOperation::TOpPaintTextureRegion: { MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); ThebesLayerComposite* thebes = static_cast<ThebesLayerComposite*>(compositable->GetLayer()); const ThebesBufferData& bufferData = op.bufferData(); RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds()); nsIntRegion frontUpdatedRegion; compositable->UpdateThebes(bufferData, op.updatedRegion(), thebes->GetValidRegion(), &frontUpdatedRegion); replyv.push_back( OpContentBufferSwap(compositableParent, nullptr, frontUpdatedRegion)); RenderTraceInvalidateEnd(thebes, "FF00FF"); break; } case CompositableOperation::TOpUpdatePictureRect: { const OpUpdatePictureRect& op = aEdit.get_OpUpdatePictureRect(); CompositableHost* compositable = static_cast<CompositableParent*>(op.compositableParent())->GetCompositableHost(); MOZ_ASSERT(compositable); compositable->SetPictureRect(op.picture()); break; } case CompositableOperation::TOpPaintTiledLayerBuffer: { MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer")); const OpPaintTiledLayerBuffer& op = aEdit.get_OpPaintTiledLayerBuffer(); CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent()); CompositableHost* compositable = compositableParent->GetCompositableHost(); TiledLayerComposer* tileComposer = compositable->AsTiledLayerComposer(); NS_ASSERTION(tileComposer, "compositable is not a tile composer"); BasicTiledLayerBuffer* p = reinterpret_cast<BasicTiledLayerBuffer*>(op.tiledLayerBuffer()); tileComposer->PaintedTiledLayerBuffer(p); break; } default: { MOZ_ASSERT(false, "bad type"); } } return true; }
void nuiGLPainter::UploadTexture(nuiTexture* pTexture) { nuiSurface* pSurface = pTexture->GetSurface(); float Width = pTexture->GetUnscaledWidth(); float Height = pTexture->GetUnscaledHeight(); GLenum target = GetTextureTarget(pTexture->IsPowerOfTwo()); bool changedctx = false; std::map<nuiTexture*, TextureInfo>::iterator it = mTextures.find(pTexture); if (it == mTextures.end()) it = mTextures.insert(mTextures.begin(), std::pair<nuiTexture*, TextureInfo>(pTexture, TextureInfo())); NGL_ASSERT(it != mTextures.end()); TextureInfo& info(it->second); nuiCheckForGLErrors(); if (!pTexture->IsPowerOfTwo()) { switch (GetRectangleTextureSupport()) { case 0: Width = pTexture->GetWidthPOT(); Height = pTexture->GetHeightPOT(); break; case 1: case 2: break; } } //NGL_OUT(_T("Apply Target: 0x%x\n"), target); nglImage* pImage = pTexture->GetImage(); { bool firstload = false; bool reload = info.mReload; if (!pSurface && !(pImage && pImage->GetPixelSize())) return; uint i; if (info.mTexture == (GLuint)-1) { // Generate a texture // if (mpSharedContext) // { // mpSharedContext->MakeCurrent(); // nuiCheckForGLErrors(); // changedctx = true; // } glGenTextures(1, &info.mTexture); //NGL_OUT(_T("nuiGLPainter::UploadTexture 0x%x : '%ls' / %d\n"), pTexture, pTexture->GetSource().GetChars(), info.mTexture); nuiCheckForGLErrors(); firstload = true; reload = true; } glBindTexture(target, info.mTexture); nuiCheckForGLErrors(); if (reload) { int type = 8; GLint pixelformat = 0; GLint internalPixelformat = 0; GLbyte* pBuffer = NULL; bool allocated = false; if (pImage) { type = pImage->GetBitDepth(); pixelformat = pImage->GetPixelFormat(); internalPixelformat = pImage->GetPixelFormat(); pBuffer = (GLbyte*)pImage->GetBuffer(); if (!GetRectangleTextureSupport()) { nuiCheckForGLErrors(); if (!pTexture->IsPowerOfTwo()) { pBuffer = (GLbyte*)malloc( (uint)(Width * Height * pImage->GetPixelSize())); if (!pBuffer) return; allocated = true; memset(pBuffer,0, (uint)(Width*Height * pImage->GetPixelSize())); for (i=0; i < pImage->GetHeight(); i++) { memcpy ( pBuffer + (uint)(Width * i * pImage->GetPixelSize()), pImage->GetBuffer() + pImage->GetBytesPerLine()*i, pImage->GetBytesPerLine() ); } } } glPixelStorei(GL_UNPACK_ALIGNMENT,1); nuiCheckForGLErrors(); switch (type) { case 16: case 15: type = GL_UNSIGNED_SHORT_5_5_5_1; break; case 8: case 24: case 32: type = GL_UNSIGNED_BYTE; break; } #if !defined(_OPENGL_ES_) && defined(_MACOSX_) glTexParameteri(target, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); #endif } else { NGL_ASSERT(pSurface); #if !defined(_OPENGL_ES_) && defined(_MACOSX_) internalPixelformat = pSurface->GetPixelFormat(); if (internalPixelformat == GL_RGBA) { internalPixelformat = GL_RGBA; pixelformat = GL_BGRA; type = GL_UNSIGNED_INT_8_8_8_8_REV; } else if (internalPixelformat == GL_RGB) { internalPixelformat = GL_RGB; pixelformat = GL_BGR; type = GL_UNSIGNED_BYTE; } else { pixelformat = pSurface->GetPixelFormat(); type = GL_UNSIGNED_BYTE; } glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); #else internalPixelformat = pSurface->GetPixelFormat(); pixelformat = pSurface->GetPixelFormat(); type = GL_UNSIGNED_BYTE; #endif } #ifndef _MACOSX_ if (!firstload) { glTexSubImage2D ( target, 0, 0,0, (int)Width, (int)Height, pixelformat, type, pBuffer ); nuiCheckForGLErrors(); pTexture->ResetForceReload(); } else #endif { #ifndef _OPENGL_ES_ if (pTexture->GetAutoMipMap()) { #ifdef _MACOSX_ glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); nuiCheckForGLErrors(); #endif glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, (int)log2(Width)); nuiCheckForGLErrors(); gluBuild2DMipmaps(target, internalPixelformat, (int)Width, (int)Height, pixelformat, type, pBuffer); nuiCheckForGLErrors(); } else #endif { glTexImage2D(target, 0, internalPixelformat, (int)Width, (int)Height, 0, pixelformat, type, pBuffer); } nuiCheckForGLErrors(); } info.mReload = false; if (allocated) free(pBuffer); //#FIXME // if (!pTexture->IsBufferRetained()) { // pTexture->ReleaseBuffer(); // } glTexParameteri(target, GL_TEXTURE_MIN_FILTER, pTexture->GetMinFilter()); nuiCheckForGLErrors(); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, pTexture->GetMagFilter()); nuiCheckForGLErrors(); glTexParameteri(target, GL_TEXTURE_WRAP_S, pTexture->GetWrapS()); nuiCheckForGLErrors(); glTexParameteri(target, GL_TEXTURE_WRAP_T, pTexture->GetWrapT()); nuiCheckForGLErrors(); } } if (pTexture->GetPixelFormat() == eImagePixelAlpha) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); } else { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pTexture->GetEnvMode()); } nuiCheckForGLErrors(); if (changedctx) { mpContext->BeginSession(); nuiCheckForGLErrors(); glBindTexture(target, info.mTexture); nuiCheckForGLErrors(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pTexture->GetEnvMode()); nuiCheckForGLErrors(); } glMatrixMode(GL_TEXTURE); nuiCheckForGLErrors(); glLoadIdentity(); nuiCheckForGLErrors(); uint32 rectangle = GetRectangleTextureSupport(); nuiCheckForGLErrors(); double rx = 1; double ry = 1; if (rectangle != 1) { rx = pTexture->GetUnscaledWidth() / Width; ry = pTexture->GetUnscaledHeight() / Height; #ifndef _OPENGL_ES_ if (target == GL_TEXTURE_RECTANGLE_ARB) { rx *= pTexture->GetUnscaledWidth(); ry *= pTexture->GetUnscaledHeight(); } #endif } if (pSurface) { glTranslatef(0, ry, 0); ry = -ry; } #ifndef _OPENGL_ES_ glScaled(rx, ry, 1); #else glScalef((float)rx, (float)ry, 1); #endif nuiCheckForGLErrors(); glMatrixMode(GL_MODELVIEW); nuiCheckForGLErrors(); }