Ejemplo n.º 1
0
int main(int argc, char **argv)
{
	struct Config		config;
	Display			*display;
	Window			root, window;
	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
	XvPortID		port_num;
	int			surface_type_id;
	unsigned int		is_overlay, intra_unsigned;
	int			colorkey;
	XvMCContext		context;
	XvMCSurface		surface;
	XvMCBlockArray		block_array;
	XvMCMacroBlockArray	mb_array;
	unsigned int		mbw, mbh;
	unsigned int		mbx, mby;
	unsigned int		reps;
	struct timeval		start, stop, diff;
	double			diff_secs;

	ParseArgs(argc, argv, &config);

	mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
	mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;

	display = XOpenDisplay(NULL);

	if (!GetPort
	(
		display,
		config.input_width,
		config.input_height,
		XVMC_CHROMA_FORMAT_420,
		mc_types,
		2,
		&port_num,
		&surface_type_id,
		&is_overlay,
		&intra_unsigned
	))
	{
		XCloseDisplay(display);
		fprintf(stderr, "Error, unable to find a good port.\n");
		exit(1);
	}

	if (is_overlay)
	{
		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
	}
	else
	{
		colorkey = 0;
	}

	root = XDefaultRootWindow(display);
	window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);

	assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
	assert(XvMCCreateSurface(display, &context, &surface) == Success);
	assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
	assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);

	for (mby = 0; mby < mbh; ++mby)
		for (mbx = 0; mbx < mbw; ++mbx)
		{
			mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
			mb_array.macro_blocks[mby * mbw + mbx].y = mby;
			mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
			/*mb->motion_type = ;*/
			/*mb->motion_vertical_field_select = ;*/
			mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
			/*mb->PMV[0][0][0] = ;
			mb->PMV[0][0][1] = ;
			mb->PMV[0][1][0] = ;
			mb->PMV[0][1][1] = ;
			mb->PMV[1][0][0] = ;
			mb->PMV[1][0][1] = ;
			mb->PMV[1][1][0] = ;
			mb->PMV[1][1][1] = ;*/
			mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
			mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
		}

	XSelectInput(display, window, ExposureMask | KeyPressMask);
	XMapWindow(display, window);
	XSync(display, 0);

	gettimeofday(&start, NULL);

	for (reps = 0; reps < config.reps; ++reps)
	{
		if (config.pipeline & PIPELINE_STEP_MC)
		{
			assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
			assert(XvMCFlushSurface(display, &surface) == Success);
		}
		if (config.pipeline & PIPELINE_STEP_CSC)
			assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success);
	}

	gettimeofday(&stop, NULL);

	timeval_subtract(&diff, &stop, &start);
	diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;

	printf("XvMC Benchmark\n");
	printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
	printf("Pipeline: ");
	if (config.pipeline & PIPELINE_STEP_MC)
		printf("|mc|");
	if (config.pipeline & PIPELINE_STEP_CSC)
		printf("|csc|");
	if (config.pipeline & PIPELINE_STEP_SWAP)
		printf("|swap|");
	printf("\n");
	printf("Reps: %u\n", config.reps);
	printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);

	assert(XvMCDestroyBlocks(display, &block_array) == Success);
	assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
	assert(XvMCDestroySurface(display, &surface) == Success);
	assert(XvMCDestroyContext(display, &context) == Success);

	XvUngrabPort(display, port_num, CurrentTime);
	XDestroyWindow(display, window);
	XCloseDisplay(display);

	return 0;
}
Ejemplo n.º 2
0
int main(int argc, char **argv)
{
	unsigned int		output_width;
	unsigned int		output_height;
	double			acceptable_error;
	int			prompt;
	Display			*display;
	Window			root, window;
	const unsigned int	mc_types[] = {XVMC_MOCOMP | XVMC_MPEG_2};
	XvPortID		port_num;
	int			surface_type_id;
	unsigned int		is_overlay, intra_unsigned;
	int			colorkey;
	XvMCContext		context;
	XvMCSurface		surface;
	XvMCBlockArray		block_array;
	XvMCMacroBlockArray	mb_array;
	int			mbx, mby, bx, by;
	XvMCMacroBlock		*mb;
	short			*blocks;
	int			quit = 0;

	ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);

	display = XOpenDisplay(NULL);

	if (!GetPort
	(
		display,
		INPUT_WIDTH,
		INPUT_HEIGHT,
		XVMC_CHROMA_FORMAT_420,
		mc_types,
		sizeof(mc_types)/sizeof(*mc_types),
		&port_num,
		&surface_type_id,
		&is_overlay,
		&intra_unsigned
	))
	{
		XCloseDisplay(display);
		error(1, 0, "Error, unable to find a good port.\n");
	}

	if (is_overlay)
	{
		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
	}

	root = XDefaultRootWindow(display);
	window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);

	assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
	assert(XvMCCreateSurface(display, &context, &surface) == Success);
	assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
	assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);

	mb = mb_array.macro_blocks;
	blocks = block_array.blocks;

	for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
		for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
		{
			mb->x = mbx;
			mb->y = mby;
			mb->macroblock_type = XVMC_MB_TYPE_INTRA;
			/*mb->motion_type = ;*/
			/*mb->motion_vertical_field_select = ;*/
			mb->dct_type = XVMC_DCT_TYPE_FRAME;
			/*mb->PMV[0][0][0] = ;
			mb->PMV[0][0][1] = ;
			mb->PMV[0][1][0] = ;
			mb->PMV[0][1][1] = ;
			mb->PMV[1][0][0] = ;
			mb->PMV[1][0][1] = ;
			mb->PMV[1][1][0] = ;
			mb->PMV[1][1][1] = ;*/
			mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
			mb->coded_block_pattern = 0x3F;

			mb++;

			for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
				for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
				{
					const int start = 16, stop = 235, range = stop - start;

					Gradient
					(
						blocks,
						(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
						(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
						1,
						intra_unsigned
					);

					blocks += BLOCK_SIZE;
				}

			for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
				for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
				{
					const int start = 16, stop = 240, range = stop - start;

					Gradient
					(
						blocks,
						(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
						(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
						1,
						intra_unsigned
					);

					blocks += BLOCK_SIZE;

					Gradient
					(
						blocks,
						(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
						(short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
						1,
						intra_unsigned
					);

					blocks += BLOCK_SIZE;
				}
		}

	XSelectInput(display, window, ExposureMask | KeyPressMask);
	XMapWindow(display, window);
	XSync(display, 0);

	/* Test NULL context */
	assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
	/* Test NULL surface */
	assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
	/* Test bad picture structure */
	assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
	/* Test valid params */
	assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);

	/* Test NULL surface */
	assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
	/* Test bad window */
	/* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
	/*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/

	if (prompt)
	{
		puts("Press any button to quit...");

		while (!quit)
		{
			if (XPending(display) > 0)
			{
				XEvent event;

				XNextEvent(display, &event);

				switch (event.type)
				{
					case Expose:
					{
						/* Test valid params */
						assert
						(
							XvMCPutSurface
							(
								display, &surface, window,
								0, 0, INPUT_WIDTH, INPUT_HEIGHT,
								0, 0, output_width, output_height,
								XVMC_FRAME_PICTURE
							) == Success
						);
						break;
					}
					case KeyPress:
					{
						quit = 1;
						break;
					}
				}
			}
		}
	}

	assert(XvMCDestroyBlocks(display, &block_array) == Success);
	assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
	assert(XvMCDestroySurface(display, &surface) == Success);
	assert(XvMCDestroyContext(display, &context) == Success);

	XvUngrabPort(display, port_num, CurrentTime);
	XDestroyWindow(display, window);
	XCloseDisplay(display);

	return 0;
}
Ejemplo n.º 3
0
int main(int argc, char **argv)
{
	const unsigned int	width = 16, height = 16;
	const unsigned int	min_required_blocks = 1, min_required_macroblocks = 1;
	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};

	Display			*display;
	XvPortID		port_num;
	int			surface_type_id;
	unsigned int		is_overlay, intra_unsigned;
	int			colorkey;
	XvMCContext		context;
	XvMCSurface		surface;
	XvMCBlockArray		blocks = {0};
	XvMCMacroBlockArray	macroblocks = {0};

	display = XOpenDisplay(NULL);

	if (!GetPort
	(
		display,
		width,
		height,
		XVMC_CHROMA_FORMAT_420,
    		mc_types,
    		2,
    		&port_num,
    		&surface_type_id,
    		&is_overlay,
    		&intra_unsigned
	))
	{
		XCloseDisplay(display);
		error(1, 0, "Error, unable to find a good port.\n");
	}

	if (is_overlay)
	{
		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
	}

	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
	assert(XvMCCreateSurface(display, &context, &surface) == Success);

	/* Test NULL context */
	assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext);
	/* Test 0 blocks */
	assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue);
	/* Test valid params */
	assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success);
	/* Test context id assigned and correct */
	assert(blocks.context_id == context.context_id);
	/* Test number of blocks assigned and correct */
	assert(blocks.num_blocks == min_required_blocks);
	/* Test block pointer valid */
	assert(blocks.blocks != NULL);
	/* Test NULL context */
	assert(XvMCCreateMacroBlocks(display, NULL, 1, &macroblocks) == XvMCBadContext);
	/* Test 0 macroblocks */
	assert(XvMCCreateMacroBlocks(display, &context, 0, &macroblocks) == BadValue);
	/* Test valid params */
	assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, &macroblocks) == Success);
	/* Test context id assigned and correct */
	assert(macroblocks.context_id == context.context_id);
	/* Test macroblock pointer valid */
	assert(macroblocks.macro_blocks != NULL);
	/* Test valid params */
	assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
	/* Test valid params */
	assert(XvMCDestroyBlocks(display, &blocks) == Success);

	assert(XvMCDestroySurface(display, &surface) == Success);
	assert(XvMCDestroyContext(display, &context) == Success);

	XvUngrabPort(display, port_num, CurrentTime);
	XCloseDisplay(display);

	return 0;
}
Ejemplo n.º 4
0
int main(int argc, char **argv)
{
	const unsigned int	width = 16, height = 16;
	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
	const unsigned int	subpic_width = 16, subpic_height = 16;

	Display			*display;
	XvPortID		port_num;
	int			surface_type_id;
	unsigned int		is_overlay, intra_unsigned;
	int			colorkey;
	XvMCContext		context;
	XvImageFormatValues	*subpics;
	int			num_subpics;
	XvMCSubpicture		subpicture = {0};
	int			i;

	display = XOpenDisplay(NULL);

	if (!GetPort
	(
		display,
		width,
		height,
		XVMC_CHROMA_FORMAT_420,
		mc_types,
		2,
		&port_num,
		&surface_type_id,
		&is_overlay,
		&intra_unsigned
	))
	{
		XCloseDisplay(display);
		fprintf(stderr, "Error, unable to find a good port.\n");
		exit(1);
	}

	if (is_overlay)
	{
		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
	}

	assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);

	subpics = XvMCListSubpictureTypes(display, port_num, surface_type_id, &num_subpics);
	assert((subpics && num_subpics) > 0 || (!subpics && num_subpics == 0));

	for (i = 0; i < num_subpics; ++i)
	{
		printf("Subpicture %d:\n", i);
		printf("\tid: 0x%08x\n", subpics[i].id);
		printf("\ttype: %s\n", subpics[i].type == XvRGB ? "XvRGB" : (subpics[i].type == XvYUV ? "XvYUV" : "Unknown"));
		printf("\tbyte_order: %s\n", subpics[i].byte_order == LSBFirst ? "LSB First" : (subpics[i].byte_order == MSBFirst ? "MSB First" : "Unknown"));
		PrintGUID(subpics[i].guid);
		printf("\tbpp: %u\n", subpics[i].bits_per_pixel);
		printf("\tformat: %s\n", subpics[i].format == XvPacked ? "XvPacked" : (subpics[i].format == XvPlanar ? "XvPlanar" : "Unknown"));
		printf("\tnum_planes: %u\n", subpics[i].num_planes);

		if (subpics[i].type == XvRGB)
		{
			printf("\tdepth: %u\n", subpics[i].depth);
			printf("\tred_mask: 0x%08x\n", subpics[i].red_mask);
			printf("\tgreen_mask: 0x%08x\n", subpics[i].green_mask);
			printf("\tblue_mask: 0x%08x\n", subpics[i].blue_mask);
		}
		else if (subpics[i].type == XvYUV)
		{
			printf("\ty_sample_bits: %u\n", subpics[i].y_sample_bits);
			printf("\tu_sample_bits: %u\n", subpics[i].u_sample_bits);
			printf("\tv_sample_bits: %u\n", subpics[i].v_sample_bits);
			printf("\thorz_y_period: %u\n", subpics[i].horz_y_period);
			printf("\thorz_u_period: %u\n", subpics[i].horz_u_period);
			printf("\thorz_v_period: %u\n", subpics[i].horz_v_period);
			printf("\tvert_y_period: %u\n", subpics[i].vert_y_period);
			printf("\tvert_u_period: %u\n", subpics[i].vert_u_period);
			printf("\tvert_v_period: %u\n", subpics[i].vert_v_period);
		}
		PrintComponentOrder(subpics[i].component_order);
		printf("\tscanline_order: %s\n", subpics[i].scanline_order == XvTopToBottom ? "XvTopToBottom" : (subpics[i].scanline_order == XvBottomToTop ? "XvBottomToTop" : "Unknown"));
	}

	if (num_subpics == 0)
	{
		printf("Subpictures not supported, nothing to test.\n");
		return 0;
	}

	/* Test NULL context */
	assert(XvMCCreateSubpicture(display, NULL, &subpicture, subpic_width, subpic_height, subpics[0].id) == XvMCBadContext);
	/* Test NULL subpicture */
	assert(XvMCCreateSubpicture(display, &context, NULL, subpic_width, subpic_height, subpics[0].id) == XvMCBadSubpicture);
	/* Test invalid subpicture */
	assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, -1) == BadMatch);
	/* Test huge width */
	assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, subpic_height, subpics[0].id) == BadValue);
	/* Test huge height */
	assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, 16384, subpics[0].id) == BadValue);
	/* Test huge width & height */
	assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, 16384, subpics[0].id) == BadValue);
	for (i = 0; i < num_subpics; ++i)
	{
		/* Test valid params */
		assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, subpics[i].id) == Success);
		/* Test subpicture id assigned */
		assert(subpicture.subpicture_id != 0);
		/* Test context id assigned and correct */
		assert(subpicture.context_id == context.context_id);
		/* Test subpicture type id assigned and correct */
		assert(subpicture.xvimage_id == subpics[i].id);
		/* Test width & height assigned and correct */
		assert(subpicture.width == width && subpicture.height == height);
		if (subpics[i].type == XvRGB)
			/* Test no palette support */
			assert(subpicture.num_palette_entries == 0 && subpicture.entry_bytes == 0);
		else
			/* Test palette support */
			assert(subpicture.num_palette_entries == 16 && subpicture.entry_bytes == 4);
		/* Test valid params */
		assert(XvMCDestroySubpicture(display, &subpicture) == Success);
	}
	/* Test NULL surface */
	assert(XvMCDestroySubpicture(display, NULL) == XvMCBadSubpicture);

	assert(XvMCDestroyContext(display, &context) == Success);

	free(subpics);
	XvUngrabPort(display, port_num, CurrentTime);
	XCloseDisplay(display);

	return 0;
}
Ejemplo n.º 5
0
void init_display()
{
   int surface_type_id, result, i, value, scrn, num_fbconfigs;
   GLXFBConfig *fbconfigs;
   XVisualInfo *visInfo;
   XSetWindowAttributes attributes;
   Window root;
   int attrib_pbuffer[6] = {GLX_PBUFFER_WIDTH, 0, 
                            GLX_PBUFFER_HEIGHT, 0,
                            GLX_PRESERVED_CONTENTS,
                            0};

   width = horizontal_size;
   height = vertical_size;

   if(chroma_format != CHROMA420)
      error("we only support 4:2:0 chroma formats\n");

   display = XOpenDisplay(NULL);
   root = XDefaultRootWindow(display);
   scrn = XDefaultScreen(display);

   if(!GetPortId(display, &portNum, &surface_type_id))
      error("couldn't find a suitable port\n");



#ifdef USE_DLOPEN
   if(!ResolveFunctions(DLFILENAME))
      error("couldn't resolve necessary functions\n");
#endif

   result = XvMCCreateContext(display, portNum, surface_type_id, 
                              coded_picture_width, coded_picture_height,
                              XVMC_DIRECT, &context);

   if(result != Success)
      error("couldn't create XvMCContext\n");

   for(i = 0; i < numsurfaces; i++) {
      result = XvMCCreateSurface(display, &context, &surfaces[i]);
      if(result != Success) {
          if(i < 4) {
             XvMCDestroyContext(display, &context);
             error("couldn't create enough XvMCSurfaces\n");
          } else {
             numsurfaces = i;
             printf("could only allocate %i surfaces\n", numsurfaces);
          }
      } 
      surface_info[i].reference = 0;
      surface_info[i].sequence_number = 0;      
   }

   slices = slices * mb_width;

   XvMCCreateBlocks(display, &context, slices * 6, &blocks);
   XvMCCreateMacroBlocks(display, &context, slices, &macro_blocks);

   fbconfigs = glXChooseFBConfig(display, scrn, attr_fbconfig, &num_fbconfigs);

   gl_fbconfig = *fbconfigs;

   /* find the first one with no depth buffer */
   for(i = 0; i < num_fbconfigs; i++) {
      glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DEPTH_SIZE, &value);
      if(value == 0) {
         gl_fbconfig = fbconfigs[i];
         break;
      }
   }

   PrintVisual();
 
   visInfo = glXGetVisualFromFBConfig(display, gl_fbconfig);

   attrib_pbuffer[1] = width;
   attrib_pbuffer[3] = bob ? (height/2) : height;
   gl_pbuffer = glXCreatePbuffer(display, gl_fbconfig, attrib_pbuffer);

   gl_context = glXCreateNewContext(display, gl_fbconfig, GLX_RGBA_TYPE, 
                                    NULL, 1);

   attributes.colormap = XCreateColormap(display, root, visInfo->visual,
                                         AllocNone);

   window = XCreateWindow(display, root, 0, 0, width, height, 0,
                          visInfo->depth, InputOutput,
                          visInfo->visual, CWColormap, &attributes);

   gl_window = glXCreateWindow(display, gl_fbconfig, window, NULL);

   XSelectInput(display, window, KeyPressMask | StructureNotifyMask |
                                 Button1MotionMask | ButtonPressMask);
   XMapWindow(display, window);

   glXMakeContextCurrent(display, gl_window, gl_pbuffer, gl_context);
   glDrawBuffer(GL_BACK);
   glReadBuffer(GL_FRONT_LEFT);

   tex_w =  1 << PowerOfTwo(width);
   tex_h = 1 << PowerOfTwo(bob ? (height/2) : height);

   printf("%i x %i texture\n", tex_w, tex_h);

   glClearColor (0.0, 0.0, 0.0, 0.0);

   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glTexImage2D(GL_TEXTURE_2D, 0, 3, tex_w, tex_h,
                0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
   glEnable(GL_TEXTURE_2D);
   glShadeModel(GL_FLAT);

   glViewport(0, 0, width, height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1.0, 1.0, -1.0, 1.0, 2, 18.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glTranslatef(0.0, 0.0, -8);

#ifdef USE_NV_FENCE
   glGenFencesNV(1, &nvFence);
   glSetFenceNV(&nvFence, GL_ALL_COMPLETED_NV);
#endif

   XSync(display, 0);

   uiclp = uiclip+512;
   for (i= -512; i<512; i++)
      uiclp[i] = (i<-128) ? 0 : ((i>127) ? 255 : i+128);

   iclp = iclip+512;
   for (i= -512; i<512; i++)
      iclp[i] = (i<-128) ? -128 : ((i>127) ? 127 : i);

   niclp = niclip+512;
   for (i= -512; i<512; i++)
   niclp[i] = (i<-256) ? -256 : ((i>255) ? 255 : i);

}