Пример #1
0
/////////////////////////////////////////////////////////////
/// Met à jour les pixels de la texture
///
/// \param Rect : Rectangle à mettre à jour dans la texture
///
////////////////////////////////////////////////////////////
void DX9Texture::Update(const CRectangle& Rect)
{
    CA_ASSERT(CRectangle(0, 0, m_Size.x, m_Size.y).Intersects(Rect) == INT_IN, "DX9Texture::Update() : rectangle out of bounds");

    // Si le format des pixels à copier est le même que celui de la texture on fait une simple copie,
	// sinon on effectue une conversion
    if (m_Format == m_Data.GetFormat())
    {
        // Verrouillage de la texture
        D3DLOCKED_RECT LockedRect;
        RECT Lock = {Rect.Left(), Rect.Top(), Rect.Right(), Rect.Bottom()};
        DXCheck(m_Texture->LockRect(0, &LockedRect, &Lock, 0));

        // Copie des pixels
        UpdateSurface(LockedRect, Rect);

        // Déverrouillage de la texture
        m_Texture->UnlockRect(0);
    }
    else
    {
        // Récupération du device
        SmartPtr<IDirect3DDevice9, CResourceCOM> Device;
        m_Texture->GetDevice(&GetPtr(Device));

        // Création d'une texture en mémoire système pour y copier les pixels
        SmartPtr<IDirect3DSurface9, CResourceCOM> Src;
        if (FAILED(Device->CreateOffscreenPlainSurface(Rect.Width(), Rect.Height(), DX9Enum::Get(m_Data.GetFormat()), D3DPOOL_SYSTEMMEM, &GetPtr(Src), nullptr)))
            throw DX9Exception("CreateOffscreenPlainSurface", "DX9Texture::Update");

        // Verrouillage de la texture temporaire
        D3DLOCKED_RECT LockedRect;
        Src->LockRect(&LockedRect, nullptr, 0);

        // Copie des pixels
        UpdateSurface(LockedRect, Rect);

        // Déverrouillage de la texture temporaire
        Src->UnlockRect();

        // Récupération de la surface de niveau 0 de la texture
        SmartPtr<IDirect3DSurface9, CResourceCOM> Dest;
        m_Texture->GetSurfaceLevel(0, &GetPtr(Dest));

        // Copie de la surface Src sur la surface Dest (c'est ici qu'est effectuée la conversion de format)
        RECT DestRect = {Rect.Left(), Rect.Top(), Rect.Right(), Rect.Bottom()};
        if (FAILED(D3DXLoadSurfaceFromSurface(Dest, nullptr, &DestRect, Src, nullptr, nullptr, D3DX_DEFAULT, 0)))
            throw DX9Exception("D3DXLoadSurfaceFromSurface", "DX9Texture::Update");
    }

    // Génération des niveaux de mipmapping si nécessaire
    if (m_HasMipmaps)
    {
        if (m_AutoMipmaps)
            m_Texture->GenerateMipSubLevels();
        else
            D3DXFilterTexture(m_Texture, nullptr, D3DX_DEFAULT, D3DX_DEFAULT);
    }
}
Пример #2
0
////////////////////////////////////////////////////////////
/// Copie les pixels de la texture sur une surface verrouillée
///
/// \param LockedRect : Structure contenant les infos de verrouillage
/// \param Rect :       Rectangle source à copier
///
////////////////////////////////////////////////////////////
void DX9Texture::UpdateSurface(const D3DLOCKED_RECT& LockedRect, const CRectangle& Rect)
{
    // Récupération d'un pointeur sur les pixels source et destination
    unsigned char* DestPix = reinterpret_cast<unsigned char*>(LockedRect.pBits);
    const unsigned char* SrcPix = m_Data.GetData() + (Rect.Left() + Rect.Top() * m_Size.x) * GetBytesPerPixel(m_Data.GetFormat());

    // Copie des pixels sur la surface
    unsigned int Bpp = GetBytesPerPixel(m_Data.GetFormat());
    for (int i = 0; i < Rect.Height(); ++i)
    {
		std::copy(SrcPix, SrcPix + Rect.Width() * Bpp, DestPix);
        SrcPix  += m_Size.x * Bpp;
        DestPix += LockedRect.Pitch;
    }
}
Пример #3
0
/////////////////////////////////////////////////////////////
/// Met à jour les pixels de la texture
///
/// \param Rect : Rectangle à mettre à jour dans la texture
///
////////////////////////////////////////////////////////////
void GLTexture::Update(const CRectangle& Rect)
{
    CA_ASSERT(CRectangle(0, 0, m_Size.x, m_Size.y).Intersects(Rect) != INT_OUT, "GLTexture::Update() : rectangle out of bounds");

	 GLCheck(glBindTexture(GL_TEXTURE_2D, m_Texture));

    GLEnum::TPixelFmt TexFmt = GLEnum::Get(m_Format);
    GLEnum::TPixelFmt ImgFmt = GLEnum::Get(m_Data.GetFormat());

    if (FormatCompressed(m_Data.GetFormat()))
    {
#if CA_PLATFORM_DESKTOP

        // Format de pixel compressé - on utilise une extension pour uploader les pixels
        unsigned long DataSize = Rect.Width() * Rect.Height() * GetBytesPerPixel(m_Data.GetFormat());
        if (Rect.Width() == m_Size.x && Rect.Height() == m_Size.y)
        {
            // Le rectangle source couvre la totalité de l'image : on envoie directement les données
            GLRenderer::glCompressedTexSubImage2DARB(GL_TEXTURE_2D, 0, Rect.Left(), Rect.Top(), Rect.Width(), Rect.Height(), ImgFmt.Format, DataSize, m_Data.GetData());
        }
        else
        {
            // Le rectangle source ne couvre qu'une partie de l'image : on envoie une sous-image de l'image en mémoire
            CImage SubData = m_Data.SubImage(Rect);
            GLRenderer::glCompressedTexSubImage2DARB(GL_TEXTURE_2D, 0, Rect.Left(), Rect.Top(), Rect.Width(), Rect.Height(), ImgFmt.Format, DataSize, SubData.GetData());
        }

#else

		throw NEW_AO CNotImplementedException("GLTexture::Update() : compressed format is not supported\n");

#endif // CA_PLATFORM_DESKTOP

    }
    else
    {
		GLint pixelStore = 0;

		switch (m_Data.GetFormat())
		{
		case PixelFormat::L_8:		///< Luminosity 8 bits (1 byte)
			pixelStore = 1;
			break;

		case PixelFormat::AL_88:		///< Alpha and luminosity 16 bits (2 bytes)
		case PixelFormat::ARGB_1555:	///< RGB 16 bits 1555 (2 bytes)
		case PixelFormat::ARGB_4444:	///< RGB 16 bits 4444 (2 bytes)
		case PixelFormat::PVRTC2:		///< PVR texture compression. Each pixel is 2 bits.
			pixelStore = 2;
			break;

		case PixelFormat::RGB_888:	///< RGB 24 bits 888 (3 bytes)
		case PixelFormat::RGB_DXT1:   ///< S3 DXT1 texture compression (RGB)
			//
		case PixelFormat::ARGB_8888:	///< ARGB 32 bits 8888 (4 bytes)
		case PixelFormat::PVRTC4:	  ///< PVR texture compression. Each pixel is 4 bits.
		case PixelFormat::RGBA_DXT1:  ///< S3 DXT1 texture compression (RGBA)
		case PixelFormat::RGBA_DXT3:  ///< S3 DXT3 texture compression (RGBA)
		case PixelFormat::RGBA_DXT5:  ///< S3 DXT5 texture compression (RGBA)
			pixelStore = 4;
			break;
		}

		GLCheck(glPixelStorei(GL_PACK_ALIGNMENT, pixelStore));

        if (!m_HasMipmaps || m_AutoMipmaps)
        {
            // Pas de mipmap ou génération hardware : on ne met à jour que le premier niveau
            if ((Rect.Width() == m_Size.x) && (Rect.Height() == m_Size.y))
            {
				GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0,
					0, 0, Rect.Width(), Rect.Height(), ImgFmt.Format, ImgFmt.Type, m_Data.GetData()));
            }
            else
            {
                CImage SubData = m_Data.SubImage(Rect);
				GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0,
					Rect.Left(), Rect.Top(), Rect.Width(), Rect.Height(), ImgFmt.Format, ImgFmt.Type, SubData.GetData()));
            }
        }
        else
        {

#if CA_PLATFORM_DESKTOP
            // Plusieurs niveaux de mipmapping et génération software : on met à jour tous les niveaux
            GLCheck(gluBuild2DMipmaps(GL_TEXTURE_2D, TexFmt.Internal, m_Size.x, m_Size.y, ImgFmt.Format, ImgFmt.Type, m_Data.GetData()));

#else
			if ((Rect.Width() == m_Size.x) && (Rect.Height() == m_Size.y))
			{
				GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0,
					0, 0, Rect.Width(), Rect.Height(), ImgFmt.Format, ImgFmt.Type, m_Data.GetData()));
			}
			else
			{
				CImage SubData = m_Data.SubImage(Rect);
				GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0,
					Rect.Left(), Rect.Top(), Rect.Width(), Rect.Height(), ImgFmt.Format, ImgFmt.Type, SubData.GetData()));
			}

#endif // CA_PLATFORM_DESKTOP

			GLCheck(glGenerateMipmap(GL_TEXTURE_2D));

        }
    }

    GLCheck(glBindTexture(GL_TEXTURE_2D, 0));
}