You are not logged in.

#1 2008-07-04 07:39:59

Crayon
Bad Mother Fucker

How to copy what's on the screen to use it later?

Hi, if in my game I want to copy what's on the screen to use it later. I need to copy the buffer xfb[fb]?

Is there a function to do that, I know memcpy would work, but is there a GX function?

Offline

 

#2 2008-07-07 19:13:02

RedShade
Member

Re: How to copy what's on the screen to use it later?

The xfb is sort of a lower resolution image, and is on the CPU's side. To copy parts of an image, you would use the following functions on GX:

Code:

GX_SetTexCopySrc(u16 left,u16 top,u16 wd,u16 ht);//This sets the location on the efb you want to copy from
GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap);//This is what kind of texture you want to copy from 
//format is close to the texture initializer if you know what that is.
// To make it the same format as what you are using in GRRLIB, you would set this to (width,height, GX_TF_RGBA8,GX_FALSE)

//Next, make a buffer to hold the texture:
u8 * newTexture = memalign(32, GX_GetTexBufferSize(width,height,GX_TF_RGBA8,GX_FALSE,1));

GX_CopyTex(newTexture, boolClear);//do you want to clear the buffer after copying the image portion?

Last edited by RedShade (2008-07-07 19:14:04)

Offline

 

#3 2008-07-08 06:16:44

Crayon
Bad Mother Fucker

Re: How to copy what's on the screen to use it later?

I tried this function:

Code:

/**
 * Make a snapshot of the sreen in a texture.
 * @return A texture representing the screen.
 */
u8 *GRRLIB_Screen2Texture() {
    void *my_texture;

    GX_SetTexCopySrc(0, 0, 640, 480);
    GX_SetTexCopyDst(640, 480, GX_TF_RGBA8, GX_FALSE);
    my_texture = memalign(32, 640 * 480 * 4); // GX_GetTexBufferSize(640, 480, GX_TF_RGBA8, GX_FALSE, 1)
    GX_CopyTex(my_texture, GX_FALSE);
    return my_texture;
}

It's almost working, the only problem I have is when I put back the texture on screen. There is weird pixels on the top of the screen. They appear while drawing on top of the texture (when I move the cursor or when the button is changing state).

This is my code to copy the screen to a texture:

Code:

u8 *CopiedImg;
CopiedImg = GRRLIB_Screen2Texture();

This my code to put it back on the screen:

Code:

GRRLIB_DrawImg(0, 0, 640, 480, CopiedImg, 0, 1, 1, 255);

The libOGC Documentation is not accurate on some function arguments:
http://libogc.devkitpro.org/

For example:

Code:

/*! 
 * \fn void GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap)
 * \brief Copies the embedded framebuffer(XFB) to the texture image buffer <b><i>dest</i></b> in main memory. This is useful
 *        when creating textures using the Graphics Processor(CP).
 *        If the <b><i>clear</i></b> flag is set to GX_TRUE, the EFB will be cleared to the current color(see GX_SetCopyClear()) 
 *        during the copy operation.
 *
 * \param[in] wd pointer to the image buffer in main memory. <b><i>dest</i></b> should be 32B aligned.
 * \param[in] ht flag that indicates framebuffer should be cleared if GX_TRUE.
 * \param[in] fmt \ref texfmt
 * \param[in] mipmap 
 *
 * \return none
 */

I'm so close to make this work, if you have an hint I would appreciate it a lot.

Thanks!

Offline

 

#4 2008-07-08 16:31:49

Crayon
Bad Mother Fucker

Re: How to copy what's on the screen to use it later?

This is what I get at the top of my screen:
http://i38.tinypic.com/wrc9d2.png

I cut the rest of the screenshot because all the rest is ok???

Offline

 

#5 2008-07-08 23:28:21

RedShade
Member

Re: How to copy what's on the screen to use it later?

Something is writing over your the texture, either from an incomplete draw to EFB, or between the copy of the texture and the drawing back onto the EFB :-/...

What settings are confusing? It's similar to :
GX_InitTexObj (GXTexObj *obj, void *img_ptr, u16 wd, u16 ht, u8 fmt, u8 wrap_s, u8 wrap_t, u8 mipmap)

except you don't set wrapping or texobj

have you tried it on smaller code segments? *The kind of thing that can be pasted here to look over, or on pastie or something to try out.

Last edited by RedShade (2008-07-08 23:29:14)

Offline

 

#6 2008-07-09 00:16:34

Crayon
Bad Mother Fucker

Re: How to copy what's on the screen to use it later?

Right now I'm not at home, so this is the information that I can provide. I will do some test tonight.

I'm working in C++ project, so CopiedImg is private attribute declare as u8 *. These are all the places where CopiedImg is being used:

This for my HOME page (when the HOME button is pressed). I only want draw the game screen once and to add an effect on it. CopiedImg will be used has a background image, buttons and other stuff will be draw over it:

Code:

    if(CopiedImg == NULL)
    {
        GameScreen(); // Draw the game screen
        GRRLIB_Rectangle(0, 0, 640, 480, 0xCC000000, 1); // Make the screen look disable
        CopiedImg = GRRLIB_Screen2Texture();
    }
    else
    {    // Put the copied texture on screen
        GRRLIB_DrawImg(0, 0, 640, 480, CopiedImg, 0, 1, 1, 255);
    }

    // Buttons are drawn on screen
    ExitButton[0].Paint();
    ExitButton[1].Paint();
    ExitButton[2].Paint();

When I change screen (going back in the game) this code is called, I don't know if it's proper way to free a texture:

Code:

    if(CopiedImg)
    {
        free(CopiedImg);
        CopiedImg = NULL;
    }

In my constructor I have:

Code:

    CopiedImg = NULL;

In my destructor I have:

Code:

    if(CopiedImg)
        free(CopiedImg);

Offline

 

#7 2008-07-09 06:44:56

Crayon
Bad Mother Fucker

Re: How to copy what's on the screen to use it later?

OK just a small update, I was able to make it work correctly by loading a 640x480 texture to CopiedImg before using it.

So my code in the constructor is now:

Code:

    CopiedImg = GRRLIB_LoadTexture(splash);

splash is the image I'm using for my intro screen. I don't know what is going on in GRRLIB_LoadTexture, but it is now initializing correctly.

I still want to understand the problem, so if someone has a idea on how to solve it, well post it here...

Offline

 

#8 2008-07-09 19:19:58

RedShade
Member

Re: How to copy what's on the screen to use it later?

Don't think that does anything but shift the memory around a little. You are still having a pointer that is doing:
CopiedImage -> 0;
CopiedImage -> points to splash
CopiedImage -> points to screen capture
so the logic goes:
u32 ptr = 0;
//ptr = 1; //uncommenting this line changes the result?
ptr = 2;

I believe free(ptr) is the correct way to free memalign-ed memory

I don't know if GX_DrawDone() would help in the copying of the texture or not :-/

Offline

 

#9 2008-11-22 20:52:07

Crayon
Bad Mother Fucker

Re: How to copy what's on the screen to use it later?

I think that the DCFlushRange line fixed the problem, I saw that in the snes9x-gx code.
So the function should look like this:

Code:

u8 *GRRLIB_Screen2Texture() {
    void *my_texture;

    GX_SetTexCopySrc(0, 0, 640, 480);
    GX_SetTexCopyDst(640, 480, GX_TF_RGBA8, GX_FALSE);
    my_texture = memalign(32, 640 * 480 * 4); // GX_GetTexBufferSize(640, 480, GX_TF_RGBA8, GX_FALSE, 1)
    GX_CopyTex(my_texture, GX_FALSE);
    GX_PixModeSync();
    DCFlushRange(my_texture, 640 * 480 * 4);
    return my_texture;
}

Offline

 

#10 2008-12-03 16:35:32

sammystag
Member

Re: How to copy what's on the screen to use it later?

Hi,

This function looks like just what I need, but there seems to be a bug with it (or else with GRRLIB_DrawImg) or I am misunderstanding something.

I am using this function to copy the screen buffer before rendering it so that I can re-use it - looking at the tic-tac-toe source, this seems to be correct.

If I use this function in a loop, my graphics fall off the bottom of the screen so it seems that the screen image is being rendered slightly lower down when re-draw it.

The following program demonstrates the problem. It draws a rectangle and then when you press "A" it goes into a loop which should just keep redrawing the screen as is, but in fact the rectangle falls off the bottom.

Code:

#include <wiiuse/wpad.h>
#include "GRRLIB/GRRLIB.h"

Mtx GXmodelView2D;


u8 *GRRLIB_Screen2Texture() {
    void *my_texture;

    GX_SetTexCopySrc(0, 0, 640, 480);
    GX_SetTexCopyDst(640, 480, GX_TF_RGBA8, GX_FALSE);
    my_texture = memalign(32, 640 * 480 * 4); // GX_GetTexBufferSize(640, 480, GX_TF_RGBA8, GX_FALSE, 1)
    GX_CopyTex(my_texture, GX_FALSE);
    GX_PixModeSync();
    DCFlushRange(my_texture, 640 * 480 * 4);
    return my_texture;
}


int main(){
    VIDEO_Init();
    WPAD_Init();

    GRRLIB_InitVideo();
    GRRLIB_Start();

    GRRLIB_FillScreen(0xFF000000);
    GRRLIB_Rectangle(100,100,200,100,0xFFFFFFFF,1);
    
    // copy the soon to be rendered screen to an image
    u8 *copiedImg = GRRLIB_Screen2Texture();
    
    GRRLIB_Render();

    // just wait for A to be pressed
    bool aPressed = false;
    while(!aPressed){
        WPAD_ScanPads();
        u32 wpaddown = WPAD_ButtonsDown(0);
        aPressed = (wpaddown & WPAD_BUTTON_A);

    }

    // loop copying and redrawing until A pressed again
    aPressed = false;
    while(!aPressed){
    
        // draw the previously copied screen image
        GRRLIB_DrawImg(0, 0, 640, 480, copiedImg, 0, 1, 1, 255);
        
        // free the memory
        free(copiedImg);
        
        // copy the updated screen
        copiedImg = GRRLIB_Screen2Texture();
        
        //render the screen
        GRRLIB_Render();

        // exit when we press A
        WPAD_ScanPads();
        u32 wpaddown = WPAD_ButtonsDown(0);
        aPressed = (wpaddown & WPAD_BUTTON_A);

    }
    
    free(copiedImg);
    return 0;
}

Thanks,

SammyStag

Offline

 

#11 2008-12-03 20:22:44

Crayon
Bad Mother Fucker

Re: How to copy what's on the screen to use it later?

Yes your right, since I was not using it in a loop I never felt like finding a solution for that issue. Anyway I suck with GX functions. Hopefully someone will find a solution.

Meanwhile, you could try to use this:

Code:

GRRLIB_DrawImg(0, -1, 640, 479, copiedImg, 0, 1, 1, 255);

Right now I could not test it (not at home).

Offline

 

#12 2008-12-04 16:26:07

sammystag
Member

Re: How to copy what's on the screen to use it later?

Thanks for the reply, unfortunately this doesn't seem to fix it.

I tried a few other values and strange things happen. For example

Code:

GRRLIB_DrawImg(0, -20, 640, 460, copiedImg, 0, 1, 1, 255);

has the image stretch out to the top and bottom of the screen and then horizontally as it becomes ghost like. I wasn't sure if the 4th argument should remain at 480, but that didn't seem to make any difference.

Offline

 

#13 2008-12-05 09:28:29

NoNameNo
Administrator

Re: How to copy what's on the screen to use it later?

as i already said a lot of times, be sure to use the latest libogc !!! old version produce "VOODOO gx effects". catch the svn version and tell us if it resolv your stuff.

Offline

 

#14 2008-12-07 13:51:56

sammystag
Member

Re: How to copy what's on the screen to use it later?

I've tried this again with the new libogc 1.7.0 release and am still getting the same results.

Offline

 

Board footer

Powered by FluxBB