Copy screen to texture?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
theHobbit
Posts: 65
Joined: Sat Sep 30, 2006 5:26 am

Copy screen to texture?

Post by theHobbit »

Hi there, does anyone knows how to copy the screen to a texture.
I'm trying with the pspsdk rendertarget sample and sceGuCopyImage, but with no result.


Here is the code

Code: Select all

/*
 * PSP Software Development Kit - http://www.pspdev.org
 * -----------------------------------------------------------------------
 * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
 *
 * rendertarget.c - Sample to demonstrate usage of ofscreen
 *                  texture as a render target
 *
 * Copyright (c) 2005 Jesper Svennevid
 * Copyright &#40;c&#41; 2005 Renaldas Zioma <[email protected]>
 */

#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#include <pspge.h>
#include <pspgu.h>
#include <pspgum.h>

PSP_MODULE_INFO&#40;"RenderTarget Sample", 0, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER&#41;;

#define printf	pspDebugScreenPrintf

static unsigned int __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; list&#91;262144&#93;;

typedef struct Vertex_ColorUV
&#123;
	float u, v;
	unsigned int color;
	float x,y,z;
&#125; Vertex_ColorUV;

typedef struct Vertex_Normal
&#123;
	float nx,ny,nz;
	float x,y,z;
&#125; Vertex_Normal;


typedef struct Texture
&#123;
	int format;
	int mipmap;
	int width, height, stride;
	const void* data;
&#125; Texture;

/* cube */

Vertex_ColorUV __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; cube_vertices&#91;12*3&#93; =
&#123;
	&#123;0, 0, 0xff7f0000,-1,-1, 1&#125;, // 0
	&#123;1, 0, 0xff7f0000,-1, 1, 1&#125;, // 4
	&#123;1, 1, 0xff7f0000, 1, 1, 1&#125;, // 5

	&#123;0, 0, 0xff7f0000,-1,-1, 1&#125;, // 0
	&#123;1, 1, 0xff7f0000, 1, 1, 1&#125;, // 5
	&#123;0, 1, 0xff7f0000, 1,-1, 1&#125;, // 1

	&#123;0, 0, 0xff7f0000,-1,-1,-1&#125;, // 3
	&#123;1, 0, 0xff7f0000, 1,-1,-1&#125;, // 2
	&#123;1, 1, 0xff7f0000, 1, 1,-1&#125;, // 6

	&#123;0, 0, 0xff7f0000,-1,-1,-1&#125;, // 3
	&#123;1, 1, 0xff7f0000, 1, 1,-1&#125;, // 6
	&#123;0, 1, 0xff7f0000,-1, 1,-1&#125;, // 7

	&#123;0, 0, 0xff007f00, 1,-1,-1&#125;, // 0
	&#123;1, 0, 0xff007f00, 1,-1, 1&#125;, // 3
	&#123;1, 1, 0xff007f00, 1, 1, 1&#125;, // 7

	&#123;0, 0, 0xff007f00, 1,-1,-1&#125;, // 0
	&#123;1, 1, 0xff007f00, 1, 1, 1&#125;, // 7
	&#123;0, 1, 0xff007f00, 1, 1,-1&#125;, // 4

	&#123;0, 0, 0xff007f00,-1,-1,-1&#125;, // 0
	&#123;1, 0, 0xff007f00,-1, 1,-1&#125;, // 3
	&#123;1, 1, 0xff007f00,-1, 1, 1&#125;, // 7

	&#123;0, 0, 0xff007f00,-1,-1,-1&#125;, // 0
	&#123;1, 1, 0xff007f00,-1, 1, 1&#125;, // 7
	&#123;0, 1, 0xff007f00,-1,-1, 1&#125;, // 4

	&#123;0, 0, 0xff00007f,-1, 1,-1&#125;, // 0
	&#123;1, 0, 0xff00007f, 1, 1,-1&#125;, // 1
	&#123;1, 1, 0xff00007f, 1, 1, 1&#125;, // 2

	&#123;0, 0, 0xff00007f,-1, 1,-1&#125;, // 0
	&#123;1, 1, 0xff00007f, 1, 1, 1&#125;, // 2
	&#123;0, 1, 0xff00007f,-1, 1, 1&#125;, // 3

	&#123;0, 0, 0xff00007f,-1,-1,-1&#125;, // 4
	&#123;1, 0, 0xff00007f,-1,-1, 1&#125;, // 7
	&#123;1, 1, 0xff00007f, 1,-1, 1&#125;, // 6

	&#123;0, 0, 0xff00007f,-1,-1,-1&#125;, // 4
	&#123;1, 1, 0xff00007f, 1,-1, 1&#125;, // 6
	&#123;0, 1, 0xff00007f, 1,-1,-1&#125;, // 5
&#125;;

/* torus */

#define TORUS_SLICES 48 // numc
#define TORUS_ROWS 48 // numt
#define TORUS_RADIUS 1.0f
#define TORUS_THICKNESS 0.5f

Vertex_Normal __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; torus_vertices&#91;TORUS_SLICES*TORUS_ROWS&#93;;
unsigned short __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; torus_indices&#91;TORUS_SLICES*TORUS_ROWS*6&#93;;


int SetupCallbacks&#40;&#41;;

void genTorus&#40; unsigned slices, unsigned rows, float radius, float thickness,
	Vertex_Normal* dstVertices, unsigned short* dstIndices &#41;;

#define BUF_WIDTH &#40;512&#41;
#define SCR_WIDTH &#40;480&#41;
#define SCR_HEIGHT &#40;272&#41;
#define PIXEL_SIZE &#40;4&#41; /* change this if you change to another screenmode */
#define FRAME_SIZE &#40;BUF_WIDTH * SCR_HEIGHT * PIXEL_SIZE&#41;
#define ZBUF_SIZE &#40;BUF_WIDTH * SCR_HEIGHT * 2&#41; /* zbuffer seems to be 16-bit? */

void drawCube&#40; Texture* texture, int val &#41;
&#123;
	// setup matrices for cube

	sceGumMatrixMode&#40;GU_PROJECTION&#41;;
	sceGumLoadIdentity&#40;&#41;;
	sceGumPerspective&#40;75.0f,16.0f/9.0f,0.5f,1000.0f&#41;;

	sceGumMatrixMode&#40;GU_VIEW&#41;;
	&#123;
		ScePspFVector3 pos = &#123;0.0f,0.0f,-2.5f&#125;;

		sceGumLoadIdentity&#40;&#41;;
		sceGumTranslate&#40;&pos&#41;;
	&#125;

	sceGumMatrixMode&#40;GU_MODEL&#41;;
	&#123;
		ScePspFVector3 rot = &#123;val * 0.263f * &#40;GU_PI/180.0f&#41;, val * 0.32f * &#40;GU_PI/180.0f&#41;, val * 0.44f * &#40;GU_PI/180.0f&#41;&#125;;

		sceGumLoadIdentity&#40;&#41;;
		sceGumRotateXYZ&#40;&rot&#41;;
	&#125;

	// setup texture

	sceGuTexMode&#40;texture->format,0,0,0&#41;;
	sceGuTexImage&#40;texture->mipmap,texture->width,texture->height,texture->stride,texture->data&#41;;
	sceGuTexFunc&#40;GU_TFX_ADD,GU_TCC_RGB&#41;;
	sceGuTexFilter&#40;GU_LINEAR,GU_LINEAR&#41;;
	sceGuTexScale&#40;1.0f,1.0f&#41;;
	sceGuTexOffset&#40;0.0f,0.0f&#41;;
	sceGuAmbientColor&#40;0xffffffff&#41;;

	sceGuEnable&#40;GU_TEXTURE_2D&#41;;

	// draw cube

	sceGumDrawArray&#40;GU_TRIANGLES,GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D,12*3,0,cube_vertices&#41;;

	sceGuDisable&#40;GU_TEXTURE_2D&#41;;
&#125;

void drawTorus&#40; int val &#41;
&#123;
	// setup a light

	ScePspFVector3 dir = &#123; 0, 0, 1 &#125;;
	sceGuLight&#40;0,GU_DIRECTIONAL,GU_DIFFUSE,&dir&#41;;
	sceGuLightColor&#40;0,GU_DIFFUSE,0x00ff4040 &#41;;
	sceGuLightAtt&#40;0,1.0f,0.0f,0.0f&#41;;
	sceGuAmbient&#40;0x00202020&#41;;

	// setup texture
	sceGuDisable&#40;GU_TEXTURE_2D&#41;;
	sceGuEnable&#40;GU_LIGHTING&#41;;
	sceGuEnable&#40;GU_LIGHT0&#41;;

	// setup matrices for torus

	sceGumMatrixMode&#40;GU_PROJECTION&#41;;
	sceGumLoadIdentity&#40;&#41;;
	sceGumPerspective&#40;75.0f,16.0f/9.0f,0.5f,1000.0f&#41;;

	sceGumMatrixMode&#40;GU_VIEW&#41;;
	&#123;
		ScePspFVector3 pos = &#123;0.0f,0.0f,-2.5f&#125;;

		sceGumLoadIdentity&#40;&#41;;
		sceGumTranslate&#40;&pos&#41;;
	&#125;

	sceGumMatrixMode&#40;GU_MODEL&#41;;
	&#123;
		ScePspFVector3 rot = &#123;val * 0.79f * &#40;GU_PI/180.0f&#41;, val * 0.98f * &#40;GU_PI/180.0f&#41;, val * 1.32f * &#40;GU_PI/180.0f&#41;&#125;;

		sceGumLoadIdentity&#40;&#41;;
		sceGumRotateXYZ&#40;&rot&#41;;
	&#125;

	// draw torus

	sceGuColor&#40;0xffffff&#41;;
	sceGumDrawArray&#40;GU_TRIANGLES,GU_NORMAL_32BITF|GU_VERTEX_32BITF|GU_INDEX_16BIT|GU_TRANSFORM_3D,sizeof&#40;torus_indices&#41;/sizeof&#40;unsigned short&#41;,torus_indices,torus_vertices&#41;;


	// restore state

	sceGuDisable&#40;GU_LIGHTING&#41;;
	sceGuDisable&#40;GU_LIGHT0&#41;;
	sceGuEnable&#40;GU_TEXTURE_2D&#41;;
&#125;



int main&#40;int argc, char* argv&#91;&#93;&#41;
&#123;
	SetupCallbacks&#40;&#41;;

	// generate geometry

	genTorus&#40; TORUS_ROWS, TORUS_SLICES, TORUS_RADIUS, TORUS_THICKNESS, torus_vertices, torus_indices &#41;;		

	// flush cache so that no stray data remains

	sceKernelDcacheWritebackAll&#40;&#41;;

	// setup Edram buffers

	void* frameBuffer = &#40;void*&#41;0;
	const void* doubleBuffer = &#40;void*&#41;0x44000;
	const void* renderTarget = &#40;void*&#41;0x88000;
	const void* depthBuffer = &#40;void*&#41;0x110000;

	// setup GU

	sceGuInit&#40;&#41;;

	sceGuStart&#40;GU_DIRECT,list&#41;;
	sceGuDrawBuffer&#40;GU_PSM_4444,frameBuffer,BUF_WIDTH&#41;;
	sceGuDispBuffer&#40;SCR_WIDTH,SCR_HEIGHT,&#40;void*&#41;doubleBuffer,BUF_WIDTH&#41;;
	sceGuDepthBuffer&#40;&#40;void*&#41;depthBuffer,BUF_WIDTH&#41;;
	sceGuOffset&#40;2048 - &#40;SCR_WIDTH/2&#41;,2048 - &#40;SCR_HEIGHT/2&#41;&#41;;
	sceGuViewport&#40;2048,2048,SCR_WIDTH,SCR_HEIGHT&#41;;
	sceGuDepthRange&#40;0xc350,0x2710&#41;;
	sceGuScissor&#40;0,0,SCR_WIDTH,SCR_HEIGHT&#41;;
	sceGuEnable&#40;GU_SCISSOR_TEST&#41;;
	sceGuDepthFunc&#40;GU_GEQUAL&#41;;
	sceGuEnable&#40;GU_DEPTH_TEST&#41;;
	sceGuFrontFace&#40;GU_CW&#41;;
	sceGuShadeModel&#40;GU_SMOOTH&#41;;
	sceGuEnable&#40;GU_CULL_FACE&#41;;
	sceGuEnable&#40;GU_TEXTURE_2D&#41;;
	sceGuFinish&#40;&#41;;
	sceGuSync&#40;0,0&#41;;

	sceDisplayWaitVblankStart&#40;&#41;;
	sceGuDisplay&#40;GU_TRUE&#41;;

	// run sample
	int val = 0;
	Texture offscreenTexture = &#123;
		GU_PSM_4444,
		0, 128, 128, 128,
		sceGeEdramGetAddr&#40;&#41; + &#40;int&#41;renderTarget
	&#125;;

	for&#40;;;&#41;
	&#123;
		sceGuStart&#40;GU_DIRECT,list&#41;;

		&#123;
			sceGuDrawBufferList&#40;GU_PSM_4444,&#40;void*&#41;renderTarget,offscreenTexture.stride&#41;;

			// setup viewport

			sceGuOffset&#40;2048 - &#40;offscreenTexture.width/2&#41;,2048 - &#40;offscreenTexture.height/2&#41;&#41;;
			sceGuViewport&#40;2048,2048,offscreenTexture.width,offscreenTexture.height&#41;;

			// clear screen

			sceGuClearColor&#40;0xffffffff&#41;;
			sceGuClearDepth&#40;0&#41;;
			sceGuClear&#40;GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT&#41;;

			// draw torus to offscreen texture

			drawTorus&#40; val &#41;;
		&#125;

		&#123;
			// set frame buffer

			sceGuDrawBufferList&#40;GU_PSM_4444,&#40;void*&#41;frameBuffer,BUF_WIDTH&#41;;

			// setup viewport

			sceGuOffset&#40;2048 - &#40;SCR_WIDTH/2&#41;,2048 - &#40;SCR_HEIGHT/2&#41;&#41;;
			sceGuViewport&#40;2048,2048,SCR_WIDTH,SCR_HEIGHT&#41;;
			
			// clear screen

			sceGuClearColor&#40;0xff554433&#41;;
			sceGuClearDepth&#40;0&#41;;
			sceGuClear&#40;GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT&#41;;

			// draw cube using offscreen texture

			drawCube&#40; &offscreenTexture, val &#41;;

		&#125;
		
		sceGuCopyImage&#40;GU_PSM_4444,0,0,480,272,512,&#40;void*&#41;&#40;0x04000000+&#40;u32&#41;frameBuffer&#41;,0,0,128,offscreenTexture.data&#41;;

		sceGuFinish&#40;&#41;;
		sceGuSync&#40;0,0&#41;;

		sceDisplayWaitVblankStart&#40;&#41;;
		frameBuffer = sceGuSwapBuffers&#40;&#41;;

		val++;
	&#125;

	sceGuTerm&#40;&#41;;

	sceKernelExitGame&#40;&#41;;
	return 0;
&#125;

/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41;
&#123;
	sceKernelExitGame&#40;&#41;;
	return 0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41;
&#123;
	int cbid;

	cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
	sceKernelRegisterExitCallback&#40;cbid&#41;;

	sceKernelSleepThreadCB&#40;&#41;;

	return 0;
&#125;

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks&#40;void&#41;
&#123;
	int thid = 0;

	thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
	if&#40;thid >= 0&#41;
	&#123;
		sceKernelStartThread&#40;thid, 0, 0&#41;;
	&#125;

	return thid;
&#125;

/* usefull geometry functions */
void genTorus&#40; unsigned slices, unsigned rows, float radius, float thickness, Vertex_Normal* dstVertices, unsigned short* dstIndices &#41;
&#123;
	unsigned int i,j;

	// generate torus &#40;TODO&#58; tri-strips&#41;
	for &#40;j = 0; j < slices; ++j&#41;
	&#123;
		for &#40;i = 0; i < rows; ++i&#41;
		&#123;
			struct Vertex_Normal* curr = &dstVertices&#91;i+j*rows&#93;;
			float s = i + 0.5f;
			float t = j;
			float cs,ct,ss,st;

			cs = cosf&#40;s * &#40;2*GU_PI&#41;/slices&#41;;
			ct = cosf&#40;t * &#40;2*GU_PI&#41;/rows&#41;;
			ss = sinf&#40;s * &#40;2*GU_PI&#41;/slices&#41;;
			st = sinf&#40;t * &#40;2*GU_PI&#41;/rows&#41;;

			curr->nx = cs * ct;
			curr->ny = cs * st;
			curr->nz = ss;

			curr->x = &#40;radius + thickness * cs&#41; * ct;
			curr->y = &#40;radius + thickness * cs&#41; * st;
			curr->z = thickness * ss;
		&#125;
	&#125;

	for &#40;j = 0; j < slices; ++j&#41;
	&#123;
		for &#40;i = 0; i < rows; ++i&#41;
		&#123;
			unsigned short* curr = &dstIndices&#91;&#40;i+&#40;j*rows&#41;&#41;*6&#93;;
			unsigned int i1 = &#40;i+1&#41;%rows, j1 = &#40;j+1&#41;%slices;

			*curr++ = i + j * rows;
			*curr++ = i1 + j * rows;
			*curr++ = i + j1 * rows;

			*curr++ = i1 + j * rows;
			*curr++ = i1 + j1 * rows;
			*curr++ = i + j1 * rows;
		&#125;
	&#125;
&#125;

But it does nothing. Does anyone knows how to copy the screen to the texture data?

Thanks in advance!!
romero126
Posts: 200
Joined: Sat Dec 24, 2005 2:42 pm

Post by romero126 »

Code: Select all

Image* ScreenCopyImage&#40;&#41;
&#123;
	Image* image = createImage&#40;SCREEN_WIDTH, SCREEN_HEIGHT&#41;;
	if &#40;!image&#41; return NULL;

	Color *destinationData = image->data;
	Color *vram = getVramDisplayBuffer&#40;&#41;;

	int i, x, y;
	for &#40;y = 0; y < SCREEN_HEIGHT; y++&#41; &#123;
	
		for &#40;i = 0, x = 0; x < SCREEN_WIDTH; x++&#41; &#123;
			Color color = vram&#91;x + y * PSP_LINE_SIZE&#93;;
			u8 r = R&#40;color&#41;; 
			u8 g = G&#40;color&#41;;
			u8 b = B&#40;color&#41;;
			u8 a = 255; //&#40;color >> 24&#41; & 0xff; This errors out if alpha is in place!

			destinationData&#91;y * image->textureWidth + x&#93; = a << 24 | b << 16 | g << 8 | r;
		&#125;
		vram += PSP_LINE_SIZE - image->textureWidth;
	&#125;

	return image;
&#125;
User avatar
jean
Posts: 489
Joined: Sat Jan 05, 2008 2:44 am

Post by jean »

Ok, the question was "how to copy ..." so the provided code up here is right, but why to do so in software?? the example provided in sdk to render into a texture works fine, so use it.
Post Reply