IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

DirectX Discussion :

GetFrontBufferData et Ecran 16 bits


Sujet :

DirectX

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut GetFrontBufferData et Ecran 16 bits
    Bonjour a tous,

    Je suis actuellement en train de développer une petite application pour prendre des screenshot de mes deux écrans avec Direct3D.
    Pour cela, j'utilise la fonction GetFrontBufferData() qui me permet de correctement récuperer les screenshots de mes deux écrans sans problèmes et ensuite les enregistrer dans un fichier.

    Tout cela fonctionne correctement lorsque l'écran est configuré en 32 bits (par pixel pour les couleurs). Des lors que je passe l'écran en 16 bits ( pour faire des tests), je récupère une image de mauvaise qualité, avec une mauvaise résolution et qui tend vers le violet (exemple ci dessous).

    Nom : 16bits_screen_problem.jpg
Affichages : 274
Taille : 435,1 Ko

    Il y a t'il une possibilité de correctement utilisé GetFrontbufferData() avec des écrans 8 bits ou 16 bits ?

    Pour info le code utilisé actuellement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     //init
    d3dPresentationParameters.Windowed = TRUE;
    d3dPresentationParameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    d3dPresentationParameters.BackBufferFormat = d3dDisplayMode.Format; 
    d3dPresentationParameters.BackBufferHeight = d3dDisplayMode.Height;
    d3dPresentationParameters.BackBufferWidth = d3dDisplayMode.Width;
    d3dPresentationParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dPresentationParameters.SwapEffect= D3DSWAPEFFECT_DISCARD;
    d3dPresentationParameters.hDeviceWindow = hWnd;
    d3dPresentationParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
    d3dPresentationParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
     
    // capture screen
    IDirect3DSurface9* pSurface;
    g_pd3dDevice->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
    g_pd3dDevice->GetFrontBufferData(0, pSurface);
    Merci beaucoup pour votre aide !

    Dylan

  2. #2
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    J'imagine que c'est du DirectX9 / Windows XP / Vieux matériels...

    Si c'est le cas, il n'y a plus de support pour tout cela. Au mieux pour le violet, il est possible d'appliquer un filtre pour revenir à la couleur d'origine (enfin à tester). Pour du 16 bits, la qualité me semble être au niveau de ce que l'on peut en attendre (le texte est lisible).

  3. #3
    Expert confirmé

    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 376
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 376
    Points : 4 928
    Points
    4 928
    Par défaut
    bonjour,

    perso quand je vois le résultat, ça me fait juste penser à un mauvais offset quelque part. pas grand chose de plus cohérent à offrir, désolé.

  4. #4
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos réponses.

    @moldavi: Je travaille avec Direct3D9 sous Windows 7 avec du matériel relativement récent. Je cherchais juste le meilleur moyen de faire des screenshot avec directx sous Win7.
    Pour le violet, même en 16 bits, je ne trouve pas ça normal. Je devrais certes avoir une qualité moindre mais pas à ce point la. De plus, ma résolution est changée et je ne récupère qu'un morceau de l'écran dans le screenshot et non pas la totalité comme en 32 bits.

    @stardeath: C'est ce que j'imagine aussi, surtout quand je vois que ça fonctionne parfaitement en 32 bits...

    Plus d'infos sur le code si ça peut aider certains a m'apporter une réponse:

    Initialisation Direct3D:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    D3DDISPLAYMODE          d3dDisplayMode;
    D3DPRESENT_PARAMETERS   d3dPresentationParameters; //Presentation parameters (backbufferwidth,     height...)
     
    if( (pScreenInfo->g_pD3D=Direct3DCreate9(D3D_SDK_VERSION)) == NULL )
    {
        //Creates an IDirect3D9 object (parameter should always be D3D_SDK_VERSION)
        DBG("Error: Direct3DCreate9 failed");
        return FALSE;
    }
     
    if( pScreenInfo->g_pD3D->GetAdapterDisplayMode(iIndex, &d3dDisplayMode) ==  D3DERR_INVALIDCALL )
    {
        DBG("Error: GetAdapterDisplayMode failed");
        return FALSE;
    }
     
    //Fill pScreenInfo structure
    pScreenInfo->uiWidth = d3dDisplayMode.Width;
    pScreenInfo->uiHeight = d3dDisplayMode.Height;
    pScreenInfo->d3dFormat = d3dDisplayMode.Format;
     
    ZeroMemory(&d3dPresentationParameters,sizeof(D3DPRESENT_PARAMETERS));//Fills a block of memory with zeros.
    d3dPresentationParameters.Windowed = TRUE;
    d3dPresentationParameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    d3dPresentationParameters.BackBufferFormat = pScreenInfo->d3dFormat;//d3dDisplayMode.Format;//D3DFMT_A8R8G8B8;
    d3dPresentationParameters.BackBufferCount = 1;
    d3dPresentationParameters.BackBufferHeight = gScreenRect.bottom = pScreenInfo->uiHeight;
    d3dPresentationParameters.BackBufferWidth = gScreenRect.right = pScreenInfo->uiWidth;
    d3dPresentationParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dPresentationParameters.MultiSampleQuality = 0;
    d3dPresentationParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dPresentationParameters.hDeviceWindow = hWnd;
    d3dPresentationParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
    d3dPresentationParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
     
    if( pScreenInfo->g_pD3D->CreateDevice(iScreenNber,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dPresentationParameters,&pScreenInfo->g_pD3DDevice) != D3D_OK )
    {
        //Creates a device to represent the display adapter.D3DADAPTER_DEFAULT specifies the primary display adapter
        DBG("Error: CreateDevice failed");
        return FALSE;
    }
    Thread qui capture l'écran:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
        if( (iRes = pScreenInfo->g_pD3DDevice->CreateOffscreenPlainSurface(pScreenInfo->uiWidth, pScreenInfo->uiHeight, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pScreenInfo->pBackBuffer, NULL)) != D3D_OK )
        {
            DBG("Error: CreateOffscreenPlainSurface failed = 0x%x", iRes);
            break;
        }
     
        if( (iRes = pScreenInfo->g_pD3DDevice->GetFrontBufferData(0, pScreenInfo->pCaptureSurface)) != D3D_OK)
        {
            DBG("Error: GetFrontBufferData failed = 0x%x", iRes);
            break;
        }    
     
        //D3DXSaveSurfaceToFile("Desktop.bmp", D3DXIFF_BMP, pScreenInfo->pBackBuffer,NULL, NULL); //Test purposes
     
        ZeroMemory(&pScreenInfo->lockedRect, sizeof(D3DLOCKED_RECT));       
        if( (iRes = pScreenInfo->pBackBuffer->LockRect(&pScreenInfo->lockedRect, NULL, D3DLOCK_READONLY)) != D3D_OK )
        {
            DBG("Error: LockRect failed = 0x%x", iRes);
            break;
        }
     
        memcpy((BYTE*)pScreenInfo->pData, (BYTE*)pScreenInfo->lockedRect.pBits, pScreenInfo->bmiIn.bmiHeader.biHeight * pScreenInfo->bmiIn.bmiHeader.biWidth * pScreenInfo->bmiIn.bmiHeader.biBitCount/8); //pScreenInfo->bmiIn.bmiHeader.biSizeImage);
     
        if( (iRes = pScreenInfo->pBackBuffer->UnlockRect()) != D3D_OK )
        {
            DBG("Error: UnlockRect failed = 0x%x", iRes);
            break;
        }   
    /**/        
        SAFE_RELEASE(pScreenInfo->pCaptureSurface)
    - Ce code marche parfaitement bien en 32 bits mais pas en 16 bits
    - Dans l'init je crée 2 devices (un pour chaque écran dont je dispose). Ca marche niquel en 32 bits (mais pas en 16)
    - Lorsque j'enregistre l'impression d'écran dans un fichier bmp en 16 bits, je récupère l'écran principal parfaitement (sans violet ni probleme de résolution) mais le deuxième écran est totalement noir.
    - Dès que je veux accéder aux bits de l'image avec pData, je retrouve les problèmes du violet + de la résolution + le 2e ecran est totalement noir.

    Merci encore pour votre aide

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Après plusieurs heures de recherches, je me suis rendu compte que:
    - En sauvant la Surface utilisée (après un GetFrontBufferData) dans un fichier BMP, je récupère bien l'écran principal a chaque frame mais uniquement la première frame du deuxième écran puis celle-ci est constamment rechargée. J'ai donc toujours la toute première frame capturée pour le second écran.
    - J'ai remarqué que GetFrontBufferData qu'avec une Offscreen surface au format D3DFMT_A8R8G8B8. (soit format 32 bits avec transparence). "The buffer pointed to by pDestSurface will be filled with a representation of the front buffer, converted to the standard 32 bits per pixel format D3DFMT_A8R8G8B8."
    - Un des problèmes vient du LockRect et du memcpy qui n'est pas correctement géré --> Si quelqu'un a une idée je suis preneur )).
    - L'autre problème concernant le deuxième écran qui n'est pas géré en 16 bits et pour lequel je ne capture que la premiere frame je n'ai pas encore trouvé la source de l'erreur.

    N'hésitez pas à apporter des idées qui pourrait m'aiguiller.

    Merci a tous

    Dylan

  6. #6
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Le code ci-dessus n'est pas suffisant pour aider.

    Par contre, vous avez tous les deux certainement raison sur l'histoire d'offset. Je ne peux pas dire si le pitch est pris en compte par "pScreenInfo", il n'y a pas assez de code.Il faut regarder du côté de lockedRect.Pitch.

  7. #7
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par moldavi Voir le message
    Bonjour.

    Le code ci-dessus n'est pas suffisant pour aider.

    Par contre, vous avez tous les deux certainement raison sur l'histoire d'offset. Je ne peux pas dire si le pitch est pris en compte par "pScreenInfo", il n'y a pas assez de code.Il faut regarder du côté de lockedRect.Pitch.
    Bonjour,

    Merci pour ta réponse.

    Concernant le code, je ne sais pas trop ce que je pourrais rajouter de plus. Il s'agit des fonctions que j'ai implémentées dans l'app et il n'y a pas grand chose derrière.
    1) Je fais l'Initialiation de direct3d
    2) Puis je lance le thread
    3) J'enregistre chaque frame dans un fichier .bmp ainsi que les données de l'image dans pData avec LockRect.

    Concernant le LockRect.pitch, j'ai remarqué qu'il valait 7680 (soit 1920 (width) * 32/8 octets). Or je suis en 16 bits, ce qui fausse les résultats.

    Est-ce qu'il serait plus judicieux dans mon cas de partir sur un GetBackBuffer ? Est-ce qu'il y a déjà eu des retours sur l'utilisation de GetFrontBuffer en 16 bits ? Je n'ai vu aucun post la dessus.

    Merci

    Dylan

  8. #8
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Serait-il possible de mettre en pièce jointe les raw data d'une capture en 16Bits : le buffer lockedRect.pBits avec la hauteur/largeur et la taille du pitch. Histoire de jeter un oeil.

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par moldavi Voir le message
    Bonjour.

    Serait-il possible de mettre en pièce jointe les raw data d'une capture en 16Bits : le buffer lockedRect.pBits avec la hauteur/largeur et la taille du pitch. Histoire de jeter un oeil.
    Je ne suis pas bien sur si c'est ce que tu entends par raw data mais je t'ai mis les données que je trouve à l'adresse de lockedRect.pBits. Je ne savais pas trop ou m'arrêter, donc désolé si j'ai mis un peu trop d'information.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    pScreenInfo->bmiIn.bmiHeader.biWidth = 1920
    pScreenInfo->bmiIn.bmiHeader.biHeight = 1080
    lockedRect.pitch = 7680;
    pScreenInfo->bmiIn.bmiHeader.biBitCount=16; (16bits)
    lockedRect.pBits = 0x06320040;
    raw_data_16_bits.txt

    Merci pour ton aide

    Dylan

  10. #10
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut Capture d'écran en 16 bits
    Citation Envoyé par moldavi Voir le message
    Bonjour.

    Serait-il possible de mettre en pièce jointe les raw data d'une capture en 16Bits : le buffer lockedRect.pBits avec la hauteur/largeur et la taille du pitch. Histoire de jeter un oeil.
    Je t'ai mis les données que je trouve à l'adresse de lockedRect.pBits. Je ne savais pas trop ou m'arrêter, donc désolé si j'ai mis un peu trop d'information. Il s'agit de la première frame reçue. Je ne sais pas trop comment analyser ces données, donc si tu as des explications je suis preneur, je suis vraiment nouveau sur DirectX.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    pScreenInfo->bmiIn.bmiHeader.biWidth = 1920
    pScreenInfo->bmiIn.bmiHeader.biHeight = 1080
    lockedRect.pitch = 7680;
    pScreenInfo->bmiIn.bmiHeader.biBitCount=16; (16bits)
    lockedRect.pBits = 0x06320040;
    Raw Data joint dans la discussion (c'est ce qui a visiblement fait planter le dernier post de mettre les données en brut dans le post) :

    raw_data_16_bits.txt

    Merci pour ton aide

    Dylan

  11. #11
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Pour récupérer les data faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    if( (iRes = pScreenInfo->g_pD3DDevice->GetFrontBufferData(0, pScreenInfo->pCaptureSurface)) != D3D_OK)
        {
            DBG("Error: GetFrontBufferData failed = 0x%x", iRes);
            break;
        }    
     
    //D3DXSaveSurfaceToFile("Desktop.bmp", D3DXIFF_BMP, pScreenInfo->pBackBuffer,NULL, NULL); //Test purposes
     
    ZeroMemory(&pScreenInfo->lockedRect, sizeof(D3DLOCKED_RECT));       
    if( (iRes = pScreenInfo->pBackBuffer->LockRect(&pScreenInfo->lockedRect, NULL, D3DLOCK_READONLY)) != D3D_OK )
        {
            DBG("Error: LockRect failed = 0x%x", iRes);
            break;
        }
     
    UINT uiSize = pScreenInfo->lockedRect.Pitch * pScreenInfo->uiHeight;// Soit 7680 * 1080 d'après les informations (7680 = 1920 * 4)
    BYTE* pData = new BYTE[uiSize];
     
    memcpy(pData, pScreenInfo->lockedRect.pBits, uiSize);
     
    // Copier pData dans fichier raw (Byte par BYTE), pas un fichier texte. le fichier doit faire exactement (7680 * 1080) octets ou (uiSize) octets.
     
    delete[] pData;
     
    ...
    Pour éviter les problèmes avec le forum, il suffit certainement de zipper le fichier de data.

    //-----------------------------------------------------------------------------------
    EDIT

    J'ai testé GetFrontBufferData en mode 16bits et avec deux écrans, cela marche nickel. Je pense plutôt à un problème de CG ou de drivers (CG et WDM).

  12. #12
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par moldavi Voir le message
    Bonjour.

    Pour récupérer les data faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    if( (iRes = pScreenInfo->g_pD3DDevice->GetFrontBufferData(0, pScreenInfo->pCaptureSurface)) != D3D_OK)
        {
            DBG("Error: GetFrontBufferData failed = 0x%x", iRes);
            break;
        }    
     
    //D3DXSaveSurfaceToFile("Desktop.bmp", D3DXIFF_BMP, pScreenInfo->pBackBuffer,NULL, NULL); //Test purposes
     
    ZeroMemory(&pScreenInfo->lockedRect, sizeof(D3DLOCKED_RECT));       
    if( (iRes = pScreenInfo->pBackBuffer->LockRect(&pScreenInfo->lockedRect, NULL, D3DLOCK_READONLY)) != D3D_OK )
        {
            DBG("Error: LockRect failed = 0x%x", iRes);
            break;
        }
     
    UINT uiSize = pScreenInfo->lockedRect.Pitch * pScreenInfo->uiHeight;// Soit 7680 * 1080 d'après les informations (7680 = 1920 * 4)
    BYTE* pData = new BYTE[uiSize];
     
    memcpy(pData, pScreenInfo->lockedRect.pBits, uiSize);
     
    // Copier pData dans fichier raw (Byte par BYTE), pas un fichier texte. le fichier doit faire exactement (7680 * 1080) octets ou (uiSize) octets.
     
    delete[] pData;
     
    ...
    Pour éviter les problèmes avec le forum, il suffit certainement de zipper le fichier de data.

    //-----------------------------------------------------------------------------------
    EDIT

    J'ai testé GetFrontBufferData en mode 16bits et avec deux écrans, cela marche nickel. Je pense plutôt à un problème de CG ou de drivers (CG et WDM).
    Salut,

    Merci pour tes réponses ! Tu n'as rien fait de plus que ce que j'ai montrer dans mon premier post ?

    Comment as-tu vérifié que les données dans pData était les bonnes ? Et au niveau du pitch du lockedRect.pitch, tu as 7680 ou 3840 ?

    Merci encore

    Dylan

  13. #13
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    J'ai deux fichiers data0 (écran principal) et data1(ecran secondaire) dans lesquels j'ai enregistré toutes les données de pData.
    J'ai analysé les données avec XVI32 qui est un editeur hexadecimal et ça me donne des valeurs cohérentes.

    Si tu veux d'autres informations, n'hésites pas à me les demander.

    Merci encore.

    Dylan

    Raw_data.zip

  14. #14
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Les deux buffers sont corrects :

    Nom : Data1.jpg
Affichages : 270
Taille : 309,0 Ko

    Le code pour vérifier les buffers :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    HRESULT hr;
     
    HANDLE hFile = CreateFile(TEXT("data1.raw"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     
    DWORD dwBytesRead;
     
    UINT uiSize = 1920 * 1080 * 4;
    BYTE* pData = new BYTE[uiSize];
     
    BOOL b = ReadFile(hFile, pData, uiSize, &dwBytesRead, NULL);
     
    IDirect3DTexture9* pNew = NULL;
    hr = g_pD3DDevice->CreateTexture(d3dDisplayMode.Width, d3dDisplayMode.Height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pNew, NULL);
     
    D3DLOCKED_RECT lockedRect;
     
    hr = pNew->LockRect(0, &lockedRect, NULL, D3DLOCK_READONLY);
     
    memcpy(lockedRect.pBits, pData, lockedRect.Pitch * d3dDisplayMode.Height);
     
    hr = pNew->UnlockRect(0);
     
    hr = D3DXSaveTextureToFile(L"Test.bmp", D3DXIFF_BMP, pNew,NULL);
    // delete/release/etc...
    En fait GetFrontBufferData retourne une image en 32bits (même si les écrans sont en 16bits). GetFrontBufferData se charge de la conversion 16bits->32bits. Donc il faut gérer cette texture comme une texture 32bits.

    Si l'idée c'est d'avoir une texture 16bits, alors il faut faire la conversion soit même, après avoir récupérer la texture 32bits.

    Pour la conversion, il faut passer d'un format ARGB à un format R5G6B5. A vérifier quand même pour le bmp, car il existe plusieurs variantes de format 16bits :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    D3DFMT_R5G6B5
    D3DFMT_X1R5G5B5
    D3DFMT_A1R5G5B5
    Ceci veut dire que le pixel rouge qui est en 8bits, doit être converti en un pixel de 5bits, pour le vert 6bits et pour le bleu 5bits. Il faut donc effectuer le calcul manuellement pour passer une valeur de 8 bits en 5 ou 6bits.

  15. #15
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Génial ! Ceci explique donc pourquoi j'ai cette image corrompue en sortie. Ton code marche vraiment bien pour tester si les données sont bonnes.

    Ma question suivante est de savoir pourquoi est-ce que le deuxième écran ne fonctionne pas en 16 bits ? En 32 bits, je vois bien qu'a chaque frame les Test.bmp sont correctement mis à jour mais dès que je passe en 16 bits, le deuxième écran est constamment noir. Je ne récupère donc que l'écran principal.

    D'après ce que j'ai pu comprendre tu as réussi a faire fonctionner le tout avec deux écrans également ? Il y aurait il un paramètre que j'ai oublié de rajouter (tout en gardant à l'esprit qu'en 32 bits je prends bien en compte les 2 écrans) ?

    NB: Lors du CreateDevice(uiScreenNumber,...) je prends bien en compte chaque écran.

    *** EDIT:
    La première frame du deuxième écran est bien capturée mais ensuite plus rien (soit écran noir, soit il conserve la premiere frame capturée tout le long de l'éxecution de l'application)

    Citation Envoyé par moldavi Voir le message
    Pour la conversion, il faut passer d'un format ARGB à un format R5G6B5. A vérifier quand même pour le bmp, car il existe plusieurs variantes de format 16bits :

    Ceci veut dire que le pixel rouge qui est en 8bits, doit être converti en un pixel de 5bits, pour le vert 6bits et pour le bleu 5bits. Il faut donc effectuer le calcul manuellement pour passer une valeur de 8 bits en 5 ou 6bits.
    Super, je prends ça en compte parce que je vais devoir m'en servir ! Je n'avais pas bien compris cet aspect la, c'est plus clair maintenant.

    Merci encore pour ton aide !

    Dylan

  16. #16
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Pour le numéro d'écran il y deux modifications :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    #define SCREENTEST 1 // ou 0
     
    g_pD3D->GetAdapterDisplayMode(SCREENTEST, &d3dDisplayMode);
    g_pD3D->CreateDevice(SCREENTEST, D3DDEVTYPE_HAL,hwnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dPresentationParameters,&g_pD3DDevice);
    Je pense que tu as peut-être oublié de sélectionner le bon écran dans le GetAdapterDisplayMode.

  17. #17
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par moldavi Voir le message
    Bonjour.

    Pour le numéro d'écran il y deux modifications :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    #define SCREENTEST 1 // ou 0
     
    g_pD3D->GetAdapterDisplayMode(SCREENTEST, &d3dDisplayMode);
    g_pD3D->CreateDevice(SCREENTEST, D3DDEVTYPE_HAL,hwnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dPresentationParameters,&g_pD3DDevice);
    Je pense que tu as peut-être oublié de sélectionner le bon écran dans le GetAdapterDisplayMode.
    Malheureusement, je l'avais déjà correctement paramétré:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if( pScreenInfo->g_pD3D->GetAdapterDisplayMode(uiScreenNumber, &d3dDisplayMode) !=  D3D_OK)
    {
    	DBG("Error: GetAdapterDisplayMode failed");
    	return FALSE;
    }
    Le point étrange, c'est qu'il doit y avoir un lien entre le mode 16bits et 32bits qui bloque le deuxième écran. En analysant le lockedRect.pBits pour le deuxième écran je m'aperçoit bien que les données ne changent pas d'une frame à l'autre.
    Si tu as d'autres idées je suis preneur.

    Même en utilisant la fonction D3DXSaveSurfaceToFile(), je récupère parfaitement bien le premier écran mais pas le deuxième (première frame puis plus rien)

    Merci

    Dylan

  18. #18
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Cela ressemble à une corruption de mémoire de la texture.

    Il faut vérifier les correspondances Create/Release ou que la texture n'est pas assignée à autre chose.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy((BYTE*)pScreenInfo->pData, (BYTE*)pScreenInfo->lockedRect.pBits, pScreenInfo->bmiIn.bmiHeader.biHeight * pScreenInfo->bmiIn.bmiHeader.biWidth * pScreenInfo->bmiIn.bmiHeader.biBitCount/8);
    Le memcpy est un très bon candidat pour ce genre de corruption. Et si l'on ne déborde pas suffisamment, le débugueur ne signale rien, mais la texture devient noire, souvent. Comme à cette étape il y a une histoire de 16bits, c'est certainement la piste.

  19. #19
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Je me suis amusé à faire la transformation d'une texture 32bits en 16bits. Pour obtenir une image au format bmp, il faut utiliser D3DFMT_X1R5G5B5 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
     
    #define RGB16BMP(red, green, blue) ( ((red >> 3) << 10) | ((green >> 3) << 5) | (blue >> 3))
     
    HRESULT Generate16BitsFrom32Bits(IDirect3DDevice9* pDevice9, IDirect3DTexture9* pImageTexture){
     
    	HRESULT hr = S_OK;
     
    	IDirect3DTexture9* p16BitsTexture = NULL;
     
    	D3DSURFACE_DESC desc;
     
    	D3DLOCKED_RECT lrIn;
    	D3DLOCKED_RECT lrOut;
     
    	BYTE* pDataIn;
    	USHORT* pDataOut;
     
    	USHORT usPixel;
    	BYTE r, g, b;
    	UINT uiPitchIn;
    	UINT uiPitchOut;
     
    	hr = pImageTexture->GetLevelDesc(0, &desc);
     
    	// desc.Format doit être D3DFMT_A8R8G8B8
    	// assert(desc.Format == D3DFMT_A8R8G8B8);
     
    	hr = pDevice9->CreateTexture(desc.Width, desc.Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_X1R5G5B5, D3DPOOL_DEFAULT, &p16BitsTexture, NULL);
     
    	hr = pImageTexture->LockRect(0, &lrIn, NULL, 0);
    	hr = p16BitsTexture->LockRect(0, &lrOut, NULL, 0);
     
    	pDataIn = (BYTE*)lrIn.pBits;
    	pDataOut = (USHORT*)lrOut.pBits;
     
    	// En général lrIn.Pitch = desc.Width * 4, donc uiPitchIn vaut 0
    	// Si lrIn.Pitch > desc.Width * 4, alors il faudrait vérifier la validité de cette ligne ci-dessous...
    	uiPitchIn = lrIn.Pitch - ((INT)(desc.Width * 4.0f));
    	uiPitchOut = lrOut.Pitch - ((INT)(desc.Width * 2.0f));
    	uiPitchOut = UINT(uiPitchOut / 2.0f);
     
    	for(UINT ui = 0; ui < desc.Height; ui++){
     
    		for(UINT ui2 = 0; ui2 < desc.Width; ui2++){
     
    			b = *pDataIn++;
    			g = *pDataIn++;
    			r = *pDataIn++;
    			*pDataIn++;// Alpha
     
    			usPixel = RGB16BMP(r, g, b);
     
    			*pDataOut++ = usPixel;
    		}
     
    		// Normalement uiPitchIn = 0...
    		pDataIn += uiPitchIn;
    		pDataOut += uiPitchOut;
    	}
     
    	hr = pImageTexture->UnlockRect(0);
    	hr = p16BitsTexture->UnlockRect(0);
     
    	hr = D3DXSaveTextureToFile(L"Image16bits.bmp", D3DXIFF_BMP, p16BitsTexture, NULL);
     
    	p16BitsTexture->Release();
     
    	return hr;
    }

  20. #20
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 13
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par moldavi Voir le message
    Bonjour.

    Cela ressemble à une corruption de mémoire de la texture.

    Il faut vérifier les correspondances Create/Release ou que la texture n'est pas assignée à autre chose.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy((BYTE*)pScreenInfo->pData, (BYTE*)pScreenInfo->lockedRect.pBits, pScreenInfo->bmiIn.bmiHeader.biHeight * pScreenInfo->bmiIn.bmiHeader.biWidth * pScreenInfo->bmiIn.bmiHeader.biBitCount/8);
    Le memcpy est un très bon candidat pour ce genre de corruption. Et si l'on ne déborde pas suffisamment, le débugueur ne signale rien, mais la texture devient noire, souvent. Comme à cette étape il y a une histoire de 16bits, c'est certainement la piste.
    Tu as tout à fait raison. J'ai juste fait des essais en commentant le memcpy et en sauvant le contenu de la surface dans un .BMP (D3DXSaveSurfaceToFile) et la, Victoire ! Je récupère bien les deux écrans qui sont mis à jour !
    On sait d'ou vient le problème maintenant et je t'en remercie ! Je vais essayer de creuser pour voir si j'arrive à trouver a quoi cela peut-être dû.

    Ce que je ne comprends pas, c'est en quoi un memcpy de pBits vers pData puisse corrompre la texture ?

    Citation Envoyé par moldavi Voir le message
    Bonjour.

    Je me suis amusé à faire la transformation d'une texture 32bits en 16bits. Pour obtenir une image au format bmp, il faut utiliser D3DFMT_X1R5G5B5 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
     
    #define RGB16BMP(red, green, blue) ( ((red >> 3) << 10) | ((green >> 3) << 5) | (blue >> 3))
     
    HRESULT Generate16BitsFrom32Bits(IDirect3DDevice9* pDevice9, IDirect3DTexture9* pImageTexture){
     
    	HRESULT hr = S_OK;
     
    	IDirect3DTexture9* p16BitsTexture = NULL;
     
    	D3DSURFACE_DESC desc;
     
    	D3DLOCKED_RECT lrIn;
    	D3DLOCKED_RECT lrOut;
     
    	BYTE* pDataIn;
    	USHORT* pDataOut;
     
    	USHORT usPixel;
    	BYTE r, g, b;
    	UINT uiPitchIn;
    	UINT uiPitchOut;
     
    	hr = pImageTexture->GetLevelDesc(0, &desc);
     
    	// desc.Format doit être D3DFMT_A8R8G8B8
    	// assert(desc.Format == D3DFMT_A8R8G8B8);
     
    	hr = pDevice9->CreateTexture(desc.Width, desc.Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_X1R5G5B5, D3DPOOL_DEFAULT, &p16BitsTexture, NULL);
     
    	hr = pImageTexture->LockRect(0, &lrIn, NULL, 0);
    	hr = p16BitsTexture->LockRect(0, &lrOut, NULL, 0);
     
    	pDataIn = (BYTE*)lrIn.pBits;
    	pDataOut = (USHORT*)lrOut.pBits;
     
    	// En général lrIn.Pitch = desc.Width * 4, donc uiPitchIn vaut 0
    	// Si lrIn.Pitch > desc.Width * 4, alors il faudrait vérifier la validité de cette ligne ci-dessous...
    	uiPitchIn = lrIn.Pitch - ((INT)(desc.Width * 4.0f));
    	uiPitchOut = lrOut.Pitch - ((INT)(desc.Width * 2.0f));
    	uiPitchOut = UINT(uiPitchOut / 2.0f);
     
    	for(UINT ui = 0; ui < desc.Height; ui++){
     
    		for(UINT ui2 = 0; ui2 < desc.Width; ui2++){
     
    			b = *pDataIn++;
    			g = *pDataIn++;
    			r = *pDataIn++;
    			*pDataIn++;// Alpha
     
    			usPixel = RGB16BMP(r, g, b);
     
    			*pDataOut++ = usPixel;
    		}
     
    		// Normalement uiPitchIn = 0...
    		pDataIn += uiPitchIn;
    		pDataOut += uiPitchOut;
    	}
     
    	hr = pImageTexture->UnlockRect(0);
    	hr = p16BitsTexture->UnlockRect(0);
     
    	hr = D3DXSaveTextureToFile(L"Image16bits.bmp", D3DXIFF_BMP, p16BitsTexture, NULL);
     
    	p16BitsTexture->Release();
     
    	return hr;
    }
    C'est génial cette solution. Je pensais que ce serait plus compliqué que ça. Cependant j'ai quelques questions:
    - Tu n'utilises plus que des textures dans le programme ? Qu'en est-il des surfaces ?
    - Tu penses qu'il est plus adapté d'utiliser des textures que des surfaces dans ce genre de situation ?
    - Quel est le but de cette ligne ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    uiPitchIn = lrIn.Pitch - ((INT)(desc.Width * 4.0f));
    Merci mille fois pour ton aide, ça me permet vraiment de bien avancer !!

Discussions similaires

  1. Ecran bleu Windows 7 64 bits
    Par alex_m94 dans le forum Windows 7
    Réponses: 71
    Dernier message: 06/07/2010, 16h48
  2. Ecran figé 64 Bits
    Par pierrei dans le forum Windows 7
    Réponses: 3
    Dernier message: 21/02/2010, 12h37
  3. Cherche l'algo crc 16 bits
    Par icepower dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 21/08/2002, 14h27
  4. [TP]lire une ligne de l'ecran et la stocker dans une chaine
    Par Bleuarff dans le forum Turbo Pascal
    Réponses: 26
    Dernier message: 02/07/2002, 11h08
  5. Lire 1 bit d'un fichier en C
    Par Anonymous dans le forum C
    Réponses: 3
    Dernier message: 23/05/2002, 19h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo