Esempio n. 1
0
static inline void
dumpArbProgram(JSONWriter &json, GLenum target)
{
    if (!glIsEnabled(target)) {
        return;
    }

    GLint program_length = 0;
    glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
    if (!program_length) {
        return;
    }

    GLchar *source = new GLchar[program_length + 1];
    source[0] = 0;
    glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
    source[program_length] = 0;

    json.beginMember(enumToString(target));
    json.writeString(source);
    json.endMember();

    delete [] source;
}
Esempio n. 2
0
	/// <summary>
	/// Execute http get request 
	/// </summary>
	/// <param name="idstr">OpenGL enum as string</param>
	/// <param name="id">OpenGL enum to query</param>
	/// <param name="type">Internal OpenGL enum type (glint, glstring)</param>
	/// <param name="dim">No of dimensions to query</param>
	void capsGroup::addCapability(string idstr, GLenum id, string type, int dim)
	{
		string errorValue = "n/a";
		// Flush OpenGL error state
		glGetError();

		if (type == "glint") 
		{
			GLint* intVal;
			intVal = new GLint[dim];
			glGetIntegerv(id, intVal);
			GLint glerr = glGetError();
			if (dim == 1)
			{
				capabilities[idstr] = to_string(intVal[0]);
			}
			else
			{
				for (int i = 0; i < dim; i++)
					capabilities[idstr + "[" + to_string(i) + "]"] = to_string(intVal[i]);
			}
			if (glerr != GL_NO_ERROR)
				capabilities[idstr] = errorValue;
			delete[] intVal;
		}

		if (type == "glint64") 
		{
			GLint64* intVal;
			intVal = new GLint64[dim];
			glGetInteger64v(id, intVal);
			string valString = "";
			for (int i = 0; i < dim; i++) {
				if (i > 0) {
					valString += " ,";
				}
				valString += to_string(intVal[i]);
			}
			GLint glerr = glGetError();
			capabilities[idstr] = valString;
			if (glerr != GL_NO_ERROR) {
				capabilities[idstr] = errorValue;
			}
			delete[] intVal;
		}

		if (type == "glintindex") 
		{
			GLint *intVal;
			intVal = new GLint[dim];
			for (int i = 0; i < dim; i++) 
				glGetIntegeri_v(id, i, &intVal[i]);
			GLint glerr = glGetError();
			if (dim == 1)
			{
				capabilities[idstr] = to_string(intVal[0]);
			}
			else
			{
				for (int i = 0; i < dim; i++)
					capabilities[idstr+"["+to_string(i)+"]"] = to_string(intVal[i]);
			}

			if (glerr != GL_NO_ERROR) 
				capabilities[idstr] = errorValue;
			delete[] intVal;
		}

		if (type == "glintfragmentprogram") 
		{
			GLint* intVal;
			intVal = new GLint[dim];
			glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, id, intVal);
			string valString = "";
			for (int i = 0; i < dim; i++) {
				if (i > 0) {
					valString += " ,";
				}
				valString += to_string(intVal[i]);
			}
			GLint glerr = glGetError();
			capabilities[idstr] = valString;
			if (glerr != GL_NO_ERROR) {
				capabilities[idstr] = errorValue;
			}
			delete[] intVal;
		}

		if (type == "glintvertexprogram") 
		{
			GLint* intVal;
			intVal = new GLint[dim];
			glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, id, intVal);
			string valString = "";
			for (int i = 0; i < dim; i++) {
				if (i > 0) {
					valString += " ,";
				}
				valString += to_string(intVal[i]);
			}
			GLint glerr = glGetError();
			capabilities[idstr] = valString;
			if (glerr != GL_NO_ERROR) {
				capabilities[idstr] = errorValue;
			}
			delete[] intVal;
		}

		if (type == "glfloat") 
		{
			GLfloat* floatVal;
			floatVal = new GLfloat[dim];
			glGetFloatv(id, floatVal);
			string valString = "";
			for (int i = 0; i < dim; i++) {
				if (i > 0) {
					valString += " ,";
				}
				valString += to_string(floatVal[i]);
			}
			GLint glerr = glGetError();
			capabilities[idstr] = valString;
			if (glerr != GL_NO_ERROR) {
				capabilities[idstr] = errorValue;
			}
			delete[] floatVal;
		}

		if (type == "glstring") 
		{
			string valString = reinterpret_cast<const char*>(glGetString(id));
			GLint glerr = glGetError();
			capabilities[idstr] = valString;
			if (glerr != GL_NO_ERROR) {
				capabilities[idstr] = "";
			}
		}
	}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBProgram_nglGetProgramivARB(JNIEnv *env, jclass clazz, jint target, jint parameterName, jlong params, jlong function_pointer) {
	GLint *params_address = (GLint *)(intptr_t)params;
	glGetProgramivARBPROC glGetProgramivARB = (glGetProgramivARBPROC)((intptr_t)function_pointer);
	glGetProgramivARB(target, parameterName, params_address);
}
Esempio n. 4
0
PIGLIT_GL_TEST_CONFIG_END

void
piglit_init(int argc, char **argv)
{
	const char *source =
		"!!ARBvp1.0\n"
		"OPTION ARB_position_invariant;\n"
		"MOV result.color, program.local[3];\n"
		"END\n";
	GLuint prog;
	GLint max_local;
	GLint i;

	piglit_require_extension("GL_ARB_vertex_program");

	prog = piglit_compile_program(GL_VERTEX_PROGRAM_ARB, source);
	glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog);

	glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
			  GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_local);

	/* Limit the test to blowing through 256MB of memory. */
	max_local = MIN2(max_local, 1024 * 1024 * 16);

	for (i = 0; i < max_local; i++) {
		float values[4];

		values[0] = i * 4;
		values[1] = i * 4 + 1;
		values[2] = i * 4 + 2;
		values[3] = i * 4 + 3;

		glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, values);
	}

	for (i = 0; i < max_local; i++) {
		float values[4], get_values[4];

		glGetProgramLocalParameterfvARB(GL_VERTEX_PROGRAM_ARB, i,
						get_values);

		values[0] = i * 4;
		values[1] = i * 4 + 1;
		values[2] = i * 4 + 2;
		values[3] = i * 4 + 3;

		if (memcmp(values, get_values, sizeof(values)) != 0) {
			fprintf(stderr, "Difference on "
				"glGetProgramLocalParameterfvARB(%d):\n", i);
			fprintf(stderr, "expected: %f %f %f %f\n",
				values[0],
				values[1],
				values[2],
				values[3]);
			fprintf(stderr, "found:    %f %f %f %f\n",
				get_values[0],
				get_values[1],
				get_values[2],
				get_values[3]);
			piglit_report_result(PIGLIT_FAIL);
		}
	}

	piglit_report_result(PIGLIT_PASS);
}
Esempio n. 5
0
void PixelShaderCache::Init()
{
	glEnable(GL_FRAGMENT_PROGRAM_ARB);
	ShaderEnabled = true;
	CurrentShader = 0;
	last_entry = NULL;
	GL_REPORT_ERRORD();

	s_displayCompileAlert = true;

	glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
	
	if(s_nMaxPixelInstructions == 0) // Some combination of drivers and hardware returns zero for some reason.
		s_nMaxPixelInstructions = 4096;
	if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxPixelInstructions = 4096;
#if CG_VERSION_NUM == 2100
	if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
	{
		s_nMaxPixelInstructions = 4096;
	}
#endif

	int maxinst, maxattribs;
	glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst);
	glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&maxattribs);
	INFO_LOG(VIDEO, "pixel max_alu=%d, max_inst=%d, max_attrib=%d", s_nMaxPixelInstructions, maxinst, maxattribs);
	
	char pmatrixprog[2048];
	sprintf(pmatrixprog, "!!ARBfp1.0"
						"TEMP R0;\n"
						"TEMP R1;\n"
						"PARAM K0 = { 0.5, 0.5, 0.5, 0.5};\n" 
						"TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
						"MUL R0, R0, program.env[%d];\n"
						"ADD R0, R0, K0;\n"
						"FLR R0, R0;\n"
						"MUL R0, R0, program.env[%d];\n"
						"DP4 R1.x, R0, program.env[%d];\n"
						"DP4 R1.y, R0, program.env[%d];\n"
						"DP4 R1.z, R0, program.env[%d];\n"
						"DP4 R1.w, R0, program.env[%d];\n"
						"ADD result.color, R1, program.env[%d];\n"
						"END\n",C_COLORMATRIX+5,C_COLORMATRIX+6, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
	glGenProgramsARB(1, &s_ColorMatrixProgram);
	SetCurrentShader(s_ColorMatrixProgram);
	glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);

	GLenum err = GL_REPORT_ERROR();
	if (err != GL_NO_ERROR) {
		ERROR_LOG(VIDEO, "Failed to create color matrix fragment program");
		glDeleteProgramsARB(1, &s_ColorMatrixProgram);
		s_ColorMatrixProgram = 0;
	}

     sprintf(pmatrixprog, "!!ARBfp1.0\n"
						"TEMP R0;\n"
						"TEMP R1;\n"
                        "TEMP R2;\n"
                        //16777215/16777216*256, 1/255, 256, 0
                        "PARAM K0 = { 255.99998474121, 0.003921568627451, 256.0, 0.0};\n"
						"PARAM K1 = { 15.0, 0.066666666666, 0.0, 0.0};\n"
                        //sample the depth value
						"TEX R2, fragment.texcoord[0], texture[0], RECT;\n"

                        //scale from [0*16777216..1*16777216] to
                        //[0*16777215..1*16777215], multiply by 256
						"MUL R0, R2.x, K0.x;\n" // *16777215/16777216*256

                        //It is easy to get bad results due to low precision
                        //here, for example converting like this:
                        //MUL R0,R0,{ 65536, 256, 1, 16777216 }
                        //FRC R0,R0
                        //gives {?, 128/255, 254/255, ?} for depth value 254/255
                        //on some gpus

                        "FLR R0.x,R0;\n"        //bits 31..24

                        "SUB R0.yzw,R0,R0.x;\n" //subtract bits 31..24 from rest
                        "MUL R0.yzw,R0,K0.z;\n" // *256
                        "FLR R0.y,R0;\n"        //bits 23..16

                        "SUB R0.zw,R0,R0.y;\n"  //subtract bits 23..16 from rest
                        "MUL R0.zw,R0,K0.z;\n"  // *256
                        "FLR R0.z,R0;\n"        //bits 15..8

                        "MOV R0.w,R0.x;\n"   //duplicate bit 31..24
                        
						"MUL R0,R0,K0.y;\n"     // /255

						"MUL R0.w,R0,K1.x;\n"   // *15
                        "FLR R0.w,R0;\n"        //bits 31..28
						"MUL R0.w,R0,K1.y;\n"   // /15

						"DP4 R1.x, R0, program.env[%d];\n"
						"DP4 R1.y, R0, program.env[%d];\n"
                        "DP4 R1.z, R0, program.env[%d];\n"
                        "DP4 R1.w, R0, program.env[%d];\n"
						"ADD result.color, R1, program.env[%d];\n"
						"END\n", C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
	glGenProgramsARB(1, &s_DepthMatrixProgram);
	SetCurrentShader(s_DepthMatrixProgram);
	glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);

	err = GL_REPORT_ERROR();
	if (err != GL_NO_ERROR) {
		ERROR_LOG(VIDEO, "Failed to create depth matrix fragment program");
		glDeleteProgramsARB(1, &s_DepthMatrixProgram);
		s_DepthMatrixProgram = 0;	
	}
	
}
Esempio n. 6
0
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
{
	GLenum err = GL_REPORT_ERROR();
	if (err != GL_NO_ERROR)
	{
		ERROR_LOG(VIDEO, "glError %08x before PS!", err);
	}

#if defined HAVE_CG && HAVE_CG
	char stropt[128];
	sprintf(stropt, "MaxLocalParams=224,NumInstructionSlots=%d", s_nMaxPixelInstructions);
	const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
	CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);

	// handle errors
	if (!cgIsProgram(tempprog))
	{
		cgDestroyProgram(tempprog);

		static int num_failures = 0;
		char szTemp[MAX_PATH];
		sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
		std::ofstream file(szTemp);
		file << pstrprogram;
		file.close();

		PanicAlert("Failed to compile pixel shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%d):\n%s",
						szTemp,
						g_cgfProf,
						cgGetLastListing(g_cgcontext));

		return false;
	}

	// handle warnings
	if (cgGetError() != CG_NO_ERROR)
	{
		WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
		WARN_LOG(VIDEO, "%s", pstrprogram);
	}

	// This looks evil - we modify the program through the const char * we got from cgGetProgramString!
	// It SHOULD not have any nasty side effects though - but you never know...
	char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
	char *plocal = strstr(pcompiledprog, "program.local");
	while (plocal != NULL)
	{
		const char *penv = "  program.env";
		memcpy(plocal, penv, 13);
		plocal = strstr(plocal+13, "program.local");
	}

	glGenProgramsARB(1, &ps.glprogid);
	SetCurrentShader(ps.glprogid);	
	glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);

	err = GL_REPORT_ERROR();
	if (err != GL_NO_ERROR)
	{
		GLint error_pos, native_limit;
		glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
		glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native_limit);
		// Error occur
		if (error_pos != -1) {
			const char *program_error = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
			char line[256];
			strncpy(line, (const char *)pcompiledprog + error_pos, 255);
			line[255] = 0;
			ERROR_LOG(VIDEO, "Error at %i: %s", error_pos, program_error);
			ERROR_LOG(VIDEO, "Line dump: \n%s", line);
		} else if (native_limit != -1) {
			ERROR_LOG(VIDEO, "Hit limit? %i", native_limit);
			// TODO
		}
		ERROR_LOG(VIDEO, "%s", pstrprogram);
		ERROR_LOG(VIDEO, "%s", pcompiledprog);
	}

	cgDestroyProgram(tempprog);
#endif

	return true;
}
Esempio n. 7
0
void
piglit_init(int argc, char **argv)
{
	GLint max_address_registers;
	unsigned i;

	(void) argc;
	(void) argv;

	piglit_require_vertex_program();
	piglit_require_fragment_program();
	piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);

	glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
			  GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
			  & max_address_registers);
	if (max_address_registers == 0) {
		/* we have to have at least one address register */
		if (! piglit_automatic)
			printf("GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB == 0\n");

		piglit_report_result(PIGLIT_FAIL);
	} else 	if (max_address_registers == 1) {
		if (piglit_is_extension_supported("GL_NV_vertex_program2_option")) {
			/* this extension requires two address regs */
			if (! piglit_automatic)
				printf("GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB "
				       "== 1\n");

			piglit_report_result(PIGLIT_FAIL);
		} else {
			piglit_report_result(PIGLIT_SKIP);
		}
	}

	for (i = 0; i < ARRAY_SIZE(progs); i++) {
		char shader_source[1024];
		int offset[2];
		char direction[2];

		/* We want the constant offset in the instruction plus the
		 * value read from the attribute to be 1.
		 */
		offset[0] = 1 - (int) attrib[(2 * i) + 0];
		offset[1] = 1 - (int) attrib[(2 * i) + 1];

		if (offset[0] < 0) {
			direction[0] = '-';
			offset[0] = -offset[0];
		} else {
			direction[0] = '+';
		}

		if (offset[1] < 0) {
			direction[1] = '-';
			offset[1] = -offset[1];
		} else {
			direction[1] = '+';
		}

		snprintf(shader_source, sizeof(shader_source),
			 vertex_source_template,
			 direction[0], offset[0],
			 direction[1], offset[1]);

		progs[i] = piglit_compile_program(GL_VERTEX_PROGRAM_ARB,
						  shader_source);
	}

	glEnable(GL_FRAGMENT_PROGRAM_ARB);
	glEnable(GL_VERTEX_PROGRAM_ARB);
	glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, piglit_ARBfp_pass_through);

	glClearColor(0.5, 0.5, 0.5, 1.0);
}
Esempio n. 8
0
bool LoadProgram(GLenum target, char * filename)
{
	//Open file
	std::ifstream programFile(filename, std::ios::in | std::ios::binary);
	if(programFile.fail())
	{
		printf("Unable to open %s\n", filename);
		return false;
	}

	//calculate the size of the file
	programFile.seekg(0, std::ios::end);
	int programSize=programFile.tellg();
	programFile.seekg(0, std::ios::beg);
	
	//allocate memory
	unsigned char * programText=new unsigned char[programSize];
	if(!programText)
	{
		printf("Unable to allocate space for program text for %s\n", filename);
		return false;
	}

	//read file
	programFile.read(reinterpret_cast<char *>(programText), programSize);
	programFile.close();

	//Send program string to OpenGL
	glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB, programSize, programText);
	
	if(programText)
		delete [] programText;
	programText=NULL;

	//Output position of any error
	int programErrorPos;
	glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &programErrorPos);
	if(programErrorPos!=-1)
		LOG::Instance()->OutputError("Program error at position %d in %s",
										programErrorPos, filename);

	//Output error/warning messages if any
	const GLubyte * programErrorString=glGetString(GL_PROGRAM_ERROR_STRING_ARB);
	if(strlen((const char *)programErrorString)>0)
	{
		LOG::Instance()->OutputMisc("Program Error String for %s:\n%s", 
										filename, programErrorString);
	}

	//Is the program under native limits? (Not supported by NV_fragment_program)
	if(target!=GL_FRAGMENT_PROGRAM_NV)
	{
		GLint underNativeLimits;
		glGetProgramivARB(target, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &underNativeLimits);
		if(underNativeLimits==0)
			LOG::Instance()->OutputError("%s exceeds native limits", filename);
	}

	//Return false in case of error
	if(programErrorPos!=-1)
		return false;

	LOG::Instance()->OutputSuccess("%s loaded successfully", filename);

	return true;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBVertexProgram_nglGetProgramivARB__IIJ(JNIEnv *__env, jclass clazz, jint target, jint pname, jlong paramsAddress) {
    glGetProgramivARBPROC glGetProgramivARB = (glGetProgramivARBPROC)tlsGetFunction(1392);
    intptr_t params = (intptr_t)paramsAddress;
    UNUSED_PARAM(clazz)
    glGetProgramivARB(target, pname, params);
}
Esempio n. 10
0
/////////////////////////////////////
// gl_arb_fragment_program_loaded()
/////////////////////////////////////
bool
GLExtensions::gl_arb_fragment_program_loaded(
   const string &header,
   bool &native, 
   const unsigned char *prog)
{
   bool success;

   if (!gl_arb_fragment_program_supported())
   {
      err_mesg(ERR_LEV_INFO, "%GL_ARB_fragment_program not supported.", header.c_str());
      native = false;
      success = false;
   }
   else
   {
#ifdef GL_ARB_fragment_program

      int i;
      unsigned char *err_buf1, *err_buf2;
      const GLubyte *err_str;
      GLint err_pos;
      GLint is_native;
      
      GLenum err = glGetError();

      err_mesg(ERR_LEV_INFO, "%sLoading program...", header.c_str());

      err_str = glGetString( GL_PROGRAM_ERROR_STRING_ARB );
      glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &err_pos );
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);      

      native = (is_native != 0);

      if (err_pos != -1)
      {
         int prog_len = strlen((const char *)prog);   assert(err_pos <= prog_len);

         int err_left = err_pos, err_right = err_pos;

         while ((err_left  > 0) && 
                  (prog[err_left-1] != '\n' &&
                   prog[err_left-1] != ';'  && 
                   prog[err_left-1] != '\r'))    err_left--;
         while ((err_right < prog_len) && 
                  (prog[err_right+1] != '\n' && 
                   prog[err_right]   != ';'  && 
                   prog[err_right+1] != '\r' && 
                   prog[err_right+1] !=  0 ))    err_right++;

         err_buf1 = new unsigned char [err_right - err_left + 2]; assert(err_buf1);
         err_buf2 = new unsigned char [err_right - err_left + 2]; assert(err_buf2);

         for (i=0; i<(err_right-err_left+1); i++) 
         {
            err_buf1[i] = prog[err_left+i];
            err_buf2[i] = ' ';
         }
         err_buf2[err_pos-err_left]='^';

         err_buf1[i] = 0;
         err_buf2[i] = 0;

      }

      if ( err == GL_INVALID_OPERATION )
      {
         success = false;

         //assert(!native);

         assert(err_str && (err_str[0] != 0));

         err_mesg(ERR_LEV_ERROR, "%s*** Failed! ***", header.c_str());
         
         if (err_pos != -1)
         {
            err_mesg(ERR_LEV_ERROR, "%sERROR LOCATION: %d",  header.c_str(), err_pos);
            err_mesg(ERR_LEV_ERROR, "%sERROR EXCERPT: [%s]", header.c_str(), err_buf1);
            err_mesg(ERR_LEV_ERROR, "%s               [%s]", header.c_str(), err_buf2);
         }

         err_mesg(ERR_LEV_ERROR, "%sERROR STRING: '%s'", header.c_str(), err_str);

      }
      else
      {
         success = true;

         if (native)
            err_mesg(ERR_LEV_INFO, "%sWill execute natively in hardware.", header.c_str());
         else
            err_mesg(ERR_LEV_WARN, "%sWill execute **BUT** not natively in hardware. Using emulation...", header.c_str());

         if (err_pos != -1)
         {
            err_mesg(ERR_LEV_WARN, "%sWARNING LOCATION: %d",  header.c_str(), err_pos);
            err_mesg(ERR_LEV_WARN, "%sWARNING EXCERPT: [%s]", header.c_str(), err_buf1);
            err_mesg(ERR_LEV_WARN, "%s                 [%s]", header.c_str(), err_buf2);
         }

         if (err_str && (err_str[0] != 0))
            err_mesg(ERR_LEV_WARN, "%sWARNING STRING: '%s'", header.c_str(), err_str);

      }

      if (err_pos != -1)
      {
         delete[] err_buf1;
         delete[] err_buf2;
      }

      GLint ins_num, ins_max, nins_num, nins_max;
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_INSTRUCTIONS_ARB,              &ins_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_INSTRUCTIONS_ARB,          &ins_max);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB,       &nins_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,   &nins_max);      

      GLint ains_num, ains_max, nains_num, nains_max;
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_ALU_INSTRUCTIONS_ARB,              &ains_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB,          &ains_max);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,       &nains_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,   &nains_max);      

      GLint tins_num, tins_max, ntins_num, ntins_max;
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_TEX_INSTRUCTIONS_ARB,              &tins_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB,          &tins_max);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,       &ntins_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,   &ntins_max);      

      GLint txns_num, txns_max, ntxns_num, ntxns_max;
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_TEX_INDIRECTIONS_ARB,              &txns_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB,          &txns_max);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB,       &ntxns_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB,   &ntxns_max);      

      GLint tmp_num, tmp_max, ntmp_num, ntmp_max;
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_TEMPORARIES_ARB,              &tmp_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_TEMPORARIES_ARB,          &tmp_max);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_NATIVE_TEMPORARIES_ARB,       &ntmp_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,   &ntmp_max);      
    
      GLint par_num, par_max, npar_num, npar_max;
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_PARAMETERS_ARB,              &par_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_PARAMETERS_ARB,          &par_max);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_NATIVE_PARAMETERS_ARB,       &npar_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB,   &npar_max);      

      GLint att_num, att_max, natt_num, natt_max;
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_ATTRIBS_ARB,              &att_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_ATTRIBS_ARB,          &att_max);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_PROGRAM_NATIVE_ATTRIBS_ARB,       &natt_num);      
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,  GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB,   &natt_max);      

      err_mesg(ERR_LEV_SPAM, "%sResource Usage:", header.c_str());
      err_mesg(ERR_LEV_SPAM, "%s  Instructions - ALL (ARB): MAX=%d  USED=%d", header.c_str(), ins_max,   ins_num);
      err_mesg(ERR_LEV_SPAM, "%s                  (NATIVE): MAX=%d  USED=%d", header.c_str(), nins_max,  nins_num);
      err_mesg(ERR_LEV_SPAM, "%s  Instructions - ALU (ARB): MAX=%d  USED=%d", header.c_str(), ains_max,  ains_num);
      err_mesg(ERR_LEV_SPAM, "%s                  (NATIVE): MAX=%d  USED=%d", header.c_str(), nains_max, nains_num);
      err_mesg(ERR_LEV_SPAM, "%s  Instructions - TEX (ARB): MAX=%d  USED=%d", header.c_str(), tins_max,  tins_num);
      err_mesg(ERR_LEV_SPAM, "%s                  (NATIVE): MAX=%d  USED=%d", header.c_str(), ntins_max, ntins_num);
      err_mesg(ERR_LEV_SPAM, "%s  Tex Indirections (ARB): MAX=%d  USED=%d",   header.c_str(), txns_max,  txns_num);
      err_mesg(ERR_LEV_SPAM, "%s                (NATIVE): MAX=%d  USED=%d",   header.c_str(), ntxns_max, ntxns_num);
      err_mesg(ERR_LEV_SPAM, "%s  Temporaries  (ARB): MAX=%d  USED=%d",       header.c_str(), tmp_max,   tmp_num);
      err_mesg(ERR_LEV_SPAM, "%s            (NATIVE): MAX=%d  USED=%d",       header.c_str(), ntmp_max,  tmp_num);
      err_mesg(ERR_LEV_SPAM, "%s  Parameters   (ARB): MAX=%d  USED=%d",       header.c_str(), par_max,   par_num);
      err_mesg(ERR_LEV_SPAM, "%s            (NATIVE): MAX=%d  USED=%d",       header.c_str(), npar_max,  npar_num);
      err_mesg(ERR_LEV_SPAM, "%s  Attributes   (ARB): MAX=%d  USED=%d",       header.c_str(), att_max,   att_num);
      err_mesg(ERR_LEV_SPAM, "%s            (NATIVE): MAX=%d  USED=%d",       header.c_str(), natt_max,  natt_num);
      err_mesg(ERR_LEV_SPAM, "%s...done.", header.c_str());
#endif
   }
   return success;
}
Esempio n. 11
0
/////////////////////////////////////////////////////////
// printInfo
//
/////////////////////////////////////////////////////////
void vertex_program :: printInfo()
{
    GLint bitnum = 0;
    if(getState()==INIT) {
        verbose(0, "not initialized yet with a valid context");
        return;
    }

    if(!GLEW_ARB_vertex_program) {
        post("no ARB vertex support!");
        return;
    }

    post("Vertex_Program Hardware Info");
    post("============================");
    glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &bitnum );
    post("MAX_VERTEX_ATTRIBS: %d", bitnum);
    glGetIntegerv( GL_MAX_PROGRAM_MATRICES_ARB, &bitnum );
    post("MAX_PROGRAM_MATRICES: %d", bitnum);
    glGetIntegerv( GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB, &bitnum );
    post("MAX_PROGRAM_MATRIX_STACK_DEPTH: %d", bitnum);

    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &bitnum);
    post("MAX_PROGRAM_INSTRUCTIONS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &bitnum);
    post("MAX_PROGRAM_NATIVE_INSTRUCTIONS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &bitnum);
    post("MAX_PROGRAM_TEMPORARIES: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &bitnum);
    post("MAX_PROGRAM_NATIVE_TEMPORARIES: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_PARAMETERS_ARB, &bitnum);
    post("MAX_PROGRAM_PARAMETERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &bitnum);
    post("MAX_PROGRAM_NATIVE_PARAMETERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ATTRIBS_ARB, &bitnum);
    post("MAX_PROGRAM_ATTRIBS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, &bitnum);
    post("MAX_PROGRAM_NATIVE_ATTRIBS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, &bitnum);
    post("MAX_PROGRAM_ADDRESS_REGISTERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, &bitnum);
    post("MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &bitnum);
    post("MAX_PROGRAM_LOCAL_PARAMETERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &bitnum);
    post("MAX_PROGRAM_ENV_PARAMETERS: %d", bitnum);
    post("");

    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_INSTRUCTIONS_ARB, &bitnum);
    post("PROGRAM_INSTRUCTIONS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &bitnum);
    post("PROGRAM_NATIVE_INSTRUCTIONS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_TEMPORARIES_ARB, &bitnum);
    post("PROGRAM_TEMPORARIES: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_TEMPORARIES_ARB, &bitnum);
    post("PROGRAM_NATIVE_TEMPORARIES: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_PARAMETERS_ARB, &bitnum);
    post("PROGRAM_PARAMETERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_PARAMETERS_ARB, &bitnum);
    post("PROGRAM_NATIVE_PARAMETERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_ATTRIBS_ARB, &bitnum);
    post("PROGRAM_ATTRIBS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_ATTRIBS_ARB, &bitnum);
    post("PROGRAM_NATIVE_ATTRIBS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_ADDRESS_REGISTERS_ARB, &bitnum);
    post("PROGRAM_ADDRESS_REGISTERS: %d", bitnum);
    glGetProgramivARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, &bitnum);
    post("PROGRAM_NATIVE_ADDRESS_REGISTERS: %d", bitnum);
}
Esempio n. 12
0
/////////////////////////////////////////////////////////
// render
//
/////////////////////////////////////////////////////////
void vertex_program :: LoadProgram(void)
{
    if(NULL==m_programString)return;
    GLint err=-1;

    if((GEM_PROGRAM_NV == m_programType) && (!GLEW_NV_vertex_program)) {
        error("NV vertex programs not supported by this system");
        return;
    }

    if((GEM_PROGRAM_ARB == m_programType) && (!GLEW_ARB_vertex_program)) {
        error("ARB vertex programs not supported by this system");
        return;
    }

    switch(m_programType) {
    case  GEM_PROGRAM_NV:
        if (m_programID==0)
        {
            glEnable(m_programTarget);
            glGenProgramsNV(1, &m_programID);
            glBindProgramNV(m_programTarget, m_programID);
            glLoadProgramNV(m_programTarget, m_programID, m_size, (GLubyte*)m_programString);
            glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &err);
        } else {
            glEnable(m_programTarget);
            glBindProgramNV(m_programTarget, m_programID);
            return;
        }
        break;
    case  GEM_PROGRAM_ARB:
        if (m_programID==0)
        {
            glEnable(m_programTarget);
            glGenProgramsARB(1, &m_programID);
            glBindProgramARB( m_programTarget, m_programID);
            glProgramStringARB( m_programTarget, GL_PROGRAM_FORMAT_ASCII_ARB, m_size, m_programString);
            glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &err);
        } else {
            glEnable(m_programTarget);
            glBindProgramARB(m_programTarget, m_programID);
            return;
        }
        break;
    default:
        return;
    }

    if(err != -1) {
        int line = 0;
        char *s = m_programString;
        while(err-- && *s) if(*s++ == '\n') line++;
        while(s >= m_programString && *s != '\n') s--;
        char *e = ++s;
        while(*e != '\n' && *e != '\0') e++;
        *e = '\0';
        error("program error at line %d:\n\"%s\"\n",line,s);
        post("%s\n", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
    }

    if(GLEW_ARB_vertex_program) {
        GLint isUnderNativeLimits;
        glGetProgramivARB( m_programTarget, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isUnderNativeLimits);

        // If the program is over the hardware's limits, print out some information
        if (isUnderNativeLimits!=1)
        {
            // Go through the most common limits that are exceeded
            error("is beyond hardware limits");

            GLint aluInstructions, maxAluInstructions;
            glGetProgramivARB(m_programTarget, GL_PROGRAM_ALU_INSTRUCTIONS_ARB, &aluInstructions);
            glGetProgramivARB(m_programTarget, GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, &maxAluInstructions);
            if (aluInstructions>maxAluInstructions)
                post("[%s]: Compiles to too many ALU instructions (%d, limit is %d)\n", m_buf.c_str(), aluInstructions, maxAluInstructions);

            GLint textureInstructions, maxTextureInstructions;
            glGetProgramivARB(m_programTarget, GL_PROGRAM_TEX_INSTRUCTIONS_ARB, &textureInstructions);
            glGetProgramivARB(m_programTarget, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, &maxTextureInstructions);
            if (textureInstructions>maxTextureInstructions)
                post("[%s]: Compiles to too many texture instructions (%d, limit is %d)\n", m_buf.c_str(), textureInstructions, maxTextureInstructions);

            GLint textureIndirections, maxTextureIndirections;
            glGetProgramivARB(m_programTarget, GL_PROGRAM_TEX_INDIRECTIONS_ARB, &textureIndirections);
            glGetProgramivARB(m_programTarget, GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, &maxTextureIndirections);
            if (textureIndirections>maxTextureIndirections)
                post("[%s]: Compiles to too many texture indirections (%d, limit is %d)\n", m_buf.c_str(), textureIndirections, maxTextureIndirections);

            GLint nativeTextureIndirections, maxNativeTextureIndirections;
            glGetProgramivARB(m_programTarget, GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, &nativeTextureIndirections);
            glGetProgramivARB(m_programTarget, GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, &maxNativeTextureIndirections);
            if (nativeTextureIndirections>maxNativeTextureIndirections)
                post("[%s]: Compiles to too many native texture indirections (%d, limit is %d)\n", m_buf.c_str(), nativeTextureIndirections, maxNativeTextureIndirections);

            GLint nativeAluInstructions, maxNativeAluInstructions;
            glGetProgramivARB(m_programTarget, GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &nativeAluInstructions);
            glGetProgramivARB(m_programTarget, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &maxNativeAluInstructions);
            if (nativeAluInstructions>maxNativeAluInstructions)
                post("[%s]: Compiles to too many native ALU instructions (%d, limit is %d)\n", m_buf.c_str(), nativeAluInstructions, maxNativeAluInstructions);
        }
    }
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBProgram_nglGetProgramivARB(JNIEnv *env, jclass clazz, jint target, jint parameterName, jobject params, jint params_position, jlong function_pointer) {
	GLint *params_address = ((GLint *)(*env)->GetDirectBufferAddress(env, params)) + params_position;
	glGetProgramivARBPROC glGetProgramivARB = (glGetProgramivARBPROC)((intptr_t)function_pointer);
	glGetProgramivARB(target, parameterName, params_address);
}
Esempio n. 14
0
bool gl_check_capability(enum gl_capability_enum enum_idx)
{
   unsigned major       = 0;
   unsigned minor       = 0;
   const char *vendor   = (const char*)glGetString(GL_VENDOR);
   const char *renderer = (const char*)glGetString(GL_RENDERER);
   const char *version  = (const char*)glGetString(GL_VERSION);
#ifdef HAVE_OPENGLES
   if (version && sscanf(version, "OpenGL ES %u.%u", &major, &minor) != 2)
#else
   if (version && sscanf(version, "%u.%u", &major, &minor) != 2)
#endif
      major = minor = 0;

   (void)vendor;

   switch (enum_idx)
   {
      case GL_CAPS_GLES3_SUPPORTED:
#if defined(HAVE_OPENGLES)
         if (major >= 3)
            return true;
#endif
         break;
      case GL_CAPS_EGLIMAGE:
#if defined(HAVE_EGL) && defined(HAVE_OPENGLES)
         if (glEGLImageTargetTexture2DOES != NULL)
            return true;
#endif
         break;
      case GL_CAPS_SYNC:
#ifdef HAVE_OPENGLES
         if (major >= 3)
            return true;
#else
         if (gl_query_extension("ARB_sync") &&
               glFenceSync && glDeleteSync && glClientWaitSync)
            return true;
#endif
         break;
      case GL_CAPS_MIPMAP:
         {
            static bool extension_queried = false;
            static bool extension         = false;

            if (!extension_queried)
            {
               extension         = gl_query_extension("ARB_framebuffer_object");
               extension_queried = true;
            }

            if (extension)
               return true;
         }
         break;
      case GL_CAPS_VAO:
#ifndef HAVE_OPENGLES
         if (!gl_query_core_context_in_use() && !gl_query_extension("ARB_vertex_array_object"))
            return false;

         if (glGenVertexArrays && glBindVertexArray && glDeleteVertexArrays)
            return true;
#endif
         break;
      case GL_CAPS_FBO:
#if defined(HAVE_PSGL) || defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES3) || defined(HAVE_OPENGLES_3_1) || defined(HAVE_OPENGLES_3_2)
         return true;
#elif defined(HAVE_FBO)
         if (!gl_query_core_context_in_use() && !gl_query_extension("ARB_framebuffer_object")
               && !gl_query_extension("EXT_framebuffer_object"))
            return false;

         if (glGenFramebuffers
               && glBindFramebuffer
               && glFramebufferTexture2D
               && glCheckFramebufferStatus
               && glDeleteFramebuffers
               && glGenRenderbuffers
               && glBindRenderbuffer
               && glFramebufferRenderbuffer
               && glRenderbufferStorage
               && glDeleteRenderbuffers)
            return true;
         break;
#else
         break;
#endif
      case GL_CAPS_ARGB8:
#ifdef HAVE_OPENGLES
         if (gl_query_extension("OES_rgb8_rgba8")
               || gl_query_extension("ARM_argb8"))
            return true;
#else
         /* TODO/FIXME - implement this for non-GLES? */
#endif
         break;
      case GL_CAPS_DEBUG:
         if (gl_query_extension("KHR_debug"))
            return true;
#ifndef HAVE_OPENGLES
         if (gl_query_extension("ARB_debug_output"))
            return true;
#endif
         break;
      case GL_CAPS_PACKED_DEPTH_STENCIL:
         {
            struct retro_hw_render_callback *hwr =
               video_driver_get_hw_context();
            if (major >= 3)
               return true;
            if (hwr->stencil
                  && !gl_query_extension("OES_packed_depth_stencil")
                  && !gl_query_extension("EXT_packed_depth_stencil"))
               return false;
         }
         return true;
      case GL_CAPS_ES2_COMPAT:
#ifndef HAVE_OPENGLES
         /* ATI card detected, skipping check for GL_RGB565 support... */
         if (vendor && renderer && (strstr(vendor, "ATI") || strstr(renderer, "ATI")))
            return false;

         if (gl_query_extension("ARB_ES2_compatibility"))
            return true;
#endif
         break;
      case GL_CAPS_UNPACK_ROW_LENGTH:
#ifdef HAVE_OPENGLES
         if (major >= 3)
            return true;

         /* Extension GL_EXT_unpack_subimage, can copy textures faster
          * than using UNPACK_ROW_LENGTH */
         if (gl_query_extension("GL_EXT_unpack_subimage"))
            return true;
#endif
         break;
      case GL_CAPS_FULL_NPOT_SUPPORT:
         if (major >= 3)
            return true;
#ifdef HAVE_OPENGLES
         if (gl_query_extension("ARB_texture_non_power_of_two") ||
               gl_query_extension("OES_texture_npot"))
            return true;
#else
         {
            GLint max_texture_size = 0;
            GLint max_native_instr = 0;
            /* try to detect actual npot support. might fail for older cards. */
            bool  arb_npot         = gl_query_extension("ARB_texture_non_power_of_two");
            bool  arb_frag_program = gl_query_extension("ARB_fragment_program");

            glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);

#ifdef GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
            if (arb_frag_program && glGetProgramivARB)
               glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
                     GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &max_native_instr);
#endif

            if (arb_npot && arb_frag_program &&
                  (max_texture_size >= 8192) && (max_native_instr >= 4096))
               return true;
         }
#endif
         break;
      case GL_CAPS_SRGB_FBO_ES3:
#ifdef HAVE_OPENGLES
         if (major >= 3)
            return true;
#else
         break;
#endif
      case GL_CAPS_SRGB_FBO:
#if defined(HAVE_OPENGLES)
         if (major >= 3 || gl_query_extension("EXT_sRGB"))
            return true;
#elif defined(HAVE_FBO)
         if (gl_query_core_context_in_use() ||
               (gl_query_extension("EXT_texture_sRGB")
                && gl_query_extension("ARB_framebuffer_sRGB")))
            return true;
#endif
         break;
      case GL_CAPS_FP_FBO:
         /* GLES - No extensions for float FBO currently. */
#ifndef HAVE_OPENGLES
#ifdef HAVE_FBO
         /* Float FBO is core in 3.2. */
         if (gl_query_core_context_in_use() || gl_query_extension("ARB_texture_float"))
            return true;
#endif
#endif
         break;
      case GL_CAPS_BGRA8888:
#ifdef HAVE_OPENGLES
         /* There are both APPLE and EXT variants. */
         /* Videocore hardware supports BGRA8888 extension, but
          * should be purposefully avoided. */
         if (gl_query_extension("BGRA8888") && !strstr(renderer, "VideoCore"))
            return true;
#else
         /* TODO/FIXME - implement this for non-GLES? */
#endif
         break;
      case GL_CAPS_NONE:
      default:
         break;
   }

   return false;
}
Esempio n. 15
0
static void R_BuildGammaProgram(void)
{
	GLint compiled;

	gammaProgram.vertexShader   = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
	gammaProgram.fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

	glShaderSourceARB(gammaProgram.vertexShader, 1, (const GLcharARB **)&simpleGammaVert, NULL);
	glShaderSourceARB(gammaProgram.fragmentShader, 1, (const GLcharARB **)&simpleGammaFrag, NULL);

	glCompileShaderARB(gammaProgram.vertexShader);
	glCompileShaderARB(gammaProgram.fragmentShader);

	glGetObjectParameterivARB(gammaProgram.vertexShader, GL_COMPILE_STATUS, &compiled);
	if (!compiled)
	{
		GLint   blen = 0;
		GLsizei slen = 0;

		glGetShaderiv(gammaProgram.vertexShader, GL_INFO_LOG_LENGTH, &blen);
		if (blen > 1)
		{
			GLchar *compiler_log;

			compiler_log = (GLchar *) malloc(blen);

			glGetInfoLogARB(gammaProgram.vertexShader, blen, &slen, compiler_log);
			Ren_Fatal("Failed to compile the gamma vertex shader reason: %s\n", compiler_log);
		}
		else
		{
			Ren_Fatal("Failed to compile the gamma vertex shader\n");
		}
	}

	glGetObjectParameterivARB(gammaProgram.fragmentShader, GL_COMPILE_STATUS, &compiled);
	if (!compiled)
	{
		Ren_Fatal("Failed to compile the gamma fragment shader\n");
	}

	gammaProgram.program = glCreateProgramObjectARB();
	if (!gammaProgram.program)
	{
		Ren_Fatal("Failed to create program\n");
	}

	glAttachObjectARB(gammaProgram.program, gammaProgram.vertexShader);
	glAttachObjectARB(gammaProgram.program, gammaProgram.fragmentShader);

	glLinkProgramARB(gammaProgram.program);

	glGetProgramivARB(gammaProgram.program, GL_LINK_STATUS, &compiled); // this throws glGetError() = 0x500
	if (!compiled)
	{
		Ren_Fatal("Failed to link gamma shaders\n");
	}

	glUseProgramObjectARB(gammaProgram.program);

	gammaProgram.currentMapUniform = glGetUniformLocation(gammaProgram.program, "u_CurrentMap");
	gammaProgram.gammaUniform      = glGetUniformLocation(gammaProgram.program, "u_gamma");

	glUseProgramObjectARB(0);
}
Esempio n. 16
0
bool ATITShader::loadVertexShaderFromFile(const char* vertPath)
{
   char fileNameBufferVert[512];
   Con::expandScriptFilename(fileNameBufferVert, sizeof(fileNameBufferVert), vertPath);
   
   const char* vs;
   
   Stream *v = ResourceManager->openStream(fileNameBufferVert);
   if(!v)
   {
      AssertWarn(false, avar("Failed to find ATIT vertex shader file: %s", fileNameBufferVert));
      return false;
   }
   
   mVertexSourceStringLength = ResourceManager->getSize(fileNameBufferVert);
   mVertexSourceString = (char *)dMalloc((mVertexSourceStringLength + 1) * sizeof(U8));
   v->read(mVertexSourceStringLength, mVertexSourceString);
   ResourceManager->closeStream(v);
   
   glEnable(GL_VERTEX_PROGRAM_ARB);
   glGenProgramsARB(1, &mVertexProgram);
   glBindProgramARB(GL_VERTEX_PROGRAM_ARB, mVertexProgram);
   glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, mVertexSourceStringLength, mVertexSourceString);
   
   #if defined(TORQUE_DEBUG) || defined(SHADER_MANAGER_DEBUG)
   const char* errorString = NULL;
   errorString = (const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
   Con::printf("Error string for %s is %s", fileNameBufferVert, errorString);
   if(errorString && errorString[0] != '\0')
      return false;
   #endif
   #ifdef ATIT_SHADER_SHOW_STATS
   bool stats = Con::getBoolVariable("$pref::shaderManager::showASMStats");
   if(stats)
   {
      GLint param;
      Con::printf("Stats for %s", fileNameBufferVert);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_INSTRUCTIONS_ARB, &param);
      Con::printf("%i instructions", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &param);
      Con::printf("%i native instructions", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_TEMPORARIES_ARB, &param);
      Con::printf("%i temporaries", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_TEMPORARIES_ARB, &param);
      Con::printf("%i native temporaries", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_PARAMETERS_ARB, &param);
      Con::printf("%i parameters", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_PARAMETERS_ARB, &param);
      Con::printf("%i native parameters", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_ATTRIBS_ARB, &param);
      Con::printf("%i attribs", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_ATTRIBS_ARB, &param);
      Con::printf("%i native attribs", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_ADDRESS_REGISTERS_ARB, &param);
      Con::printf("%i address registers", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, &param);
      Con::printf("%i native address registers", param);
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &param);
      if(param)
         Con::printf("Program is under native limits!");
      else
         Con::printf("Program exceeds native limits!");
   }
      #endif
   glDisable(GL_VERTEX_PROGRAM_ARB);
   mVertexFilepath = StringTable->insert(fileNameBufferVert);
   return true;
}
Esempio n. 17
0
bool CGLMProgram::CheckValidity( EGLMProgramLang lang )
{
	static char *targnames[] = { "vertex", "fragment" };

	switch(lang)
	{
		case kGLMARB:
		{
			GLMShaderDesc *arbDesc;
			arbDesc = &m_descs[ kGLMARB ];
			
			GLenum arbTarget = GLMProgTypeToARBEnum( m_type );

			Assert( arbDesc->m_compiled );
			
			arbDesc->m_valid = true;	// assume success til we see otherwise

			// assume program is bound.  is there anything wrong with it ?

			GLint isNative=0;
			glGetProgramivARB( arbTarget, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isNative );
			GLMCheckError();
			
			// If the program is over the hardware's limits, print out some information
			if (isNative!=1)
			{
				arbDesc->m_valid = false;
				
				// check everything we can check
				char checkmask = (1<<m_type);	// 1 for VP, 2 for FP
				
				for( GLMShaderLimitDesc *desc = g_glmShaderLimitDescs; desc->m_valueEnum !=0; desc++ )
				{
					if ( desc->m_flags & checkmask )
					{
						// test it
						GLint value = 0;
						GLint limit = 0;
						glGetProgramivARB(arbTarget, desc->m_valueEnum, &value);
						GLMCheckError();
						
						glGetProgramivARB(arbTarget, desc->m_limitEnum, &limit);
						GLMCheckError();
						
						if (value > limit)
						{
							GLMPRINTF(("-D- Invalid %s program: program has %d %s; limit is %d", targnames[ m_type ], value, desc->m_debugName, limit ));
						}
					}
				}
			}

			// syntax error check
			GLint errorLine;
			glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errorLine );
			GLMCheckError();

			if ( errorLine!=-1 )
			{
				const GLubyte* errorString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
				GLMPRINTF(( "-D- Syntax error in ARB %s program: %s",targnames[ m_type ], errorString ));
				arbDesc->m_valid = false;
			}
			if (!arbDesc->m_valid)
			{
				char *temp = strdup(m_text);
				temp[ arbDesc->m_textOffset + arbDesc->m_textLength ] = 0;
				GLMPRINTF(("-D- ----- ARB compile failed; bad source follows -----" ));
				GLMPRINTTEXT(( temp + arbDesc->m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES ));
				GLMPRINTF(("-D- -----end-----" ));
				free( temp );
			}
			
			return arbDesc->m_valid;
		}
		break;
		
		case kGLMGLSL:
		{
			GLMShaderDesc *glslDesc;			
			glslDesc = &m_descs[ kGLMGLSL ];
			
			GLenum glslStage = GLMProgTypeToGLSLEnum( m_type );

			Assert( glslDesc->m_compiled );
			
			glslDesc->m_valid = true;	// assume success til we see otherwise

			// GLSL error check
			int compiled = 0, length = 0, laux = 0;

			glGetObjectParameterivARB( (GLhandleARB)glslDesc->m_object.glsl, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
			glGetObjectParameterivARB( (GLhandleARB)glslDesc->m_object.glsl, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
			GLcharARB *logString = (GLcharARB *)malloc(length * sizeof(GLcharARB));
			glGetInfoLogARB((GLhandleARB)glslDesc->m_object.glsl, length, &laux, logString);	
			
			// we may not be able to check "native limits" stuff until link time. meh

			if (!compiled)
			{
				glslDesc->m_valid = false;
			}
			
			if (!glslDesc->m_valid)
			{
				char *temp = strdup(m_text);
				temp[ glslDesc->m_textOffset + glslDesc->m_textLength ] = 0;
				GLMPRINTF(("-D- ----- GLSL compile failed: \n %s \n",logString ));
				GLMPRINTTEXT(( temp + glslDesc->m_textOffset, eDebugDump, GLMPRINTTEXT_NUMBEREDLINES ));
				GLMPRINTF(("-D- -----end-----" ));
				free( temp );
			}
			
			free( logString );

			return glslDesc->m_valid;
		}
		break;
	}
	
	return false;
}
static inline void
dumpArbProgramUniforms(StateWriter &writer, Context &context, GLenum target, const char *prefix)
{
    if (context.ES ||
        context.core ||
        !glIsEnabled(target)) {
        return;
    }

    GLint program_parameters = 0;
    glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters);
    if (!program_parameters) {
        return;
    }

    GLint max_program_local_parameters = 0;
    glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters);
    for (GLint index = 0; index < max_program_local_parameters; ++index) {
        GLdouble params[4] = {0, 0, 0, 0};
        glGetProgramLocalParameterdvARB(target, index, params);

        if (!params[0] && !params[1] && !params[2] && !params[3]) {
            continue;
        }

        char name[256];
        snprintf(name, sizeof name, "%sprogram.local[%i]", prefix, index);

        writer.beginMember(name);
        writer.beginArray();
        writer.writeFloat(params[0]);
        writer.writeFloat(params[1]);
        writer.writeFloat(params[2]);
        writer.writeFloat(params[3]);
        writer.endArray();
        writer.endMember();
    }

    GLint max_program_env_parameters = 0;
    glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters);
    for (GLint index = 0; index < max_program_env_parameters; ++index) {
        GLdouble params[4] = {0, 0, 0, 0};
        glGetProgramEnvParameterdvARB(target, index, params);

        if (!params[0] && !params[1] && !params[2] && !params[3]) {
            continue;
        }

        char name[256];
        snprintf(name, sizeof name, "%sprogram.env[%i]", prefix, index);

        writer.beginMember(name);
        writer.beginArray();
        writer.writeFloat(params[0]);
        writer.writeFloat(params[1]);
        writer.writeFloat(params[2]);
        writer.writeFloat(params[3]);
        writer.endArray();
        writer.endMember();
    }
}
Esempio n. 19
0
/*
 * Interactive debugger
 */
static void Debugger2(GLenum target, GLvoid *data)
{
   static GLuint skipCount = 0;
   const GLubyte *ln;
   GLint pos, line, column;
   GLint id;
   int progType;
   GLint len;
   GLubyte *program;
   GLboolean stop;
   int i;

   /* Sigh, GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV so it's a bit
    * hard to distinguish between them.
    */
   if (target == GL_FRAGMENT_PROGRAM_ARB)
      progType = ARB_FRAGMENT_PROGRAM;
   else if (target == GL_FRAGMENT_PROGRAM_NV)
      progType = NV_FRAGMENT_PROGRAM;
   else
      progType = NV_VERTEX_PROGRAM;         

   /* Until we hit zero, continue rendering */
   if (skipCount > 0) {
      skipCount--;
      return;
   }

   /* Get id of the program and current position */
   switch (progType) {
   case ARB_FRAGMENT_PROGRAM:
      glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id);
      glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
      break;
   case NV_FRAGMENT_PROGRAM:
      glGetIntegerv(GL_FRAGMENT_PROGRAM_BINDING_NV, &id);
      glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
      break;
   case ARB_VERTEX_PROGRAM:
      glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id);
      glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos);
      break;
   case NV_VERTEX_PROGRAM:
      glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &id);
      glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos);
      break;
   default:
      abort();
   }

   /* get program string */
   if (progType == ARB_VERTEX_PROGRAM ||
       progType == ARB_FRAGMENT_PROGRAM)
      glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &len);
   else
      glGetProgramivNV(id, GL_PROGRAM_LENGTH_NV, &len);
   program = malloc(len + 1);
   if (progType == ARB_VERTEX_PROGRAM ||
       progType == ARB_FRAGMENT_PROGRAM)
      glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, program);
   else
      glGetProgramStringNV(id, GL_PROGRAM_STRING_NV, program);


   /* Get current line number, column, line string */
   ln = find_line_column(program, program + pos, &line, &column);

   /* test breakpoints */   
   if (NumBreakpoints > 0)
      stop = GL_FALSE;
   else
      stop = GL_TRUE;
   for (i = 0; i < NumBreakpoints; i++) {
      if (Breakpoints[i].enabled) {
         switch (Breakpoints[i].type) {
            case PIXEL:
               if (progType == ARB_FRAGMENT_PROGRAM) {

               }
               else if (progType == NV_FRAGMENT_PROGRAM) {
                  GLfloat pos[4];
                  int px, py;
                  glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
                                             6, (GLubyte *) "f[WPOS]", pos);
                  px = (int) pos[0];
                  py = (int) pos[1];
                  printf("%d, %d\n", px, py);
                  if (px == Breakpoints[i].x &&
                      py == Breakpoints[i].y) {
                     printf("Break at pixel (%d, %d)\n", px, py);
                     stop = GL_TRUE;
                  }
               }
               break;
            case LINE:
               if (line == Breakpoints[i].line) {
                  /* hit a breakpoint! */
                  printf("Break at line %d\n", line);
                  stop = GL_TRUE;
               }
               break;
         }
      }
   }
   if (!stop) {
      free(program);
      return;
   }

   printf("%d: %s\n", line, ln);

   /* get commands from stdin */
   while (1) {
      char command[1000], *cmd;

      /* print prompt and get command */
      printf("(%s %d) ", (target == GL_VERTEX_PROGRAM_ARB ? "vert" : "frag"),
             line);
      fgets(command, 999, stdin);

      /* skip leading whitespace */
      for (cmd = command; cmd[0] == ' '; cmd++)
         ;

      if (!cmd[0])
         /* nothing (repeat the previous cmd?) */
         continue;

      switch (cmd[0]) {
         case 's':
            /* skip N instructions */
            i = atoi(cmd + 2);
            skipCount = i;
            printf("Skipping %d instructions\n", i);
            return;
         case 'n':
            /* next */
            return;
         case 'c':
            return;
         case 'd':
            /* dump machine state */
            if (progType == NV_FRAGMENT_PROGRAM) {
               static const char *inRegs[] = {
                  "f[WPOS]", "f[COL0]", "f[COL1]", "f[FOGC]",
                  "f[TEX0]", "f[TEX1]", "f[TEX2]", "f[TEX3]",
                  NULL
               };
               static const char *outRegs[] = {
                  "o[COLR]", "o[COLH]", "o[DEPR]", NULL
               };
               GLfloat v[4];
               int i;
               printf("Fragment input attributes:\n");
               for (i = 0; inRegs[i]; i++) {
                  glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
                                             strlen(inRegs[i]),
                                             (const GLubyte *) inRegs[i], v);
                  printf("  %s: %g, %g, %g, %g\n", inRegs[i],
                         v[0], v[1], v[2], v[3]);
               }
               printf("Fragment output attributes:\n");
               for (i = 0; outRegs[i]; i++) {
                  glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
                                             strlen(outRegs[i]),
                                             (const GLubyte *) outRegs[i], v);
                  printf("  %s: %g, %g, %g, %g\n", outRegs[i],
                         v[0], v[1], v[2], v[3]);
               }
               printf("Temporaries:\n");
               for (i = 0; i < 4; i++) {
                  char temp[100];
                  GLfloat v[4];
                  sprintf(temp, "R%d", i);
                  glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
                                             strlen(temp),
                                             (const GLubyte *) temp, v);
                  printf("  %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]);
               }
            }
            else if (progType == NV_VERTEX_PROGRAM) {
               GLfloat v[4];
               int i;
               static const char *inRegs[] = {
                  "v[OPOS]", "v[WGHT]", "v[NRML]", "v[COL0]",
                  "v[COL1]", "v[FOGC]", "v[6]", "v[7]",
                  "v[TEX0]", "v[TEX1]", "v[TEX2]", "v[TEX3]",
                  "v[TEX4]", "v[TEX5]", "v[TEX6]", "v[TEX7]",
                  NULL
               };
               static const char *outRegs[] = {
                  "o[HPOS]", "o[COL0]", "o[COL1]", "o[BFC0]",
                  "o[BFC1]", "o[FOGC]", "o[PSIZ]",
                  "o[TEX0]", "o[TEX1]", "o[TEX2]", "o[TEX3]",
                  "o[TEX4]", "o[TEX5]", "o[TEX6]", "o[TEX7]",
                  NULL
               };
               printf("Vertex input attributes:\n");
               for (i = 0; inRegs[i]; i++) {
                  glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
                                             strlen(inRegs[i]),
                                             (const GLubyte *) inRegs[i], v);
                  printf("  %s: %g, %g, %g, %g\n", inRegs[i],
                         v[0], v[1], v[2], v[3]);
               }
               printf("Vertex output attributes:\n");
               for (i = 0; outRegs[i]; i++) {
                  glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
                                             strlen(outRegs[i]),
                                             (const GLubyte *) outRegs[i], v);
                  printf("  %s: %g, %g, %g, %g\n", outRegs[i],
                         v[0], v[1], v[2], v[3]);
               }
               printf("Temporaries:\n");
               for (i = 0; i < 4; i++) {
                  char temp[100];
                  GLfloat v[4];
                  sprintf(temp, "R%d", i);
                  glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
                                             strlen(temp),
                                             (const GLubyte *) temp, v);
                  printf("  %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]);
               }
            }
            break;
         case 'l':
            /* list */
            list_program(program, len);
            break;
         case 'p':
            /* print */
            {
               GLfloat v[4];
               char *c;
               cmd++;
               while (*cmd == ' ')
                  cmd++;
               c = cmd;
               while (*c) {
                  if (*c == '\n' || *c == '\r')
                     *c = 0;
                  else
                     c++;
               }
               glGetProgramRegisterfvMESA(target, strlen(cmd),
                                          (const GLubyte *) cmd, v);
               if (glGetError() == GL_NO_ERROR)
                  printf("%s = %g, %g, %g, %g\n", cmd, v[0], v[1], v[2], v[3]);
               else
                  printf("Invalid expression\n");
            }
            break;
         case 'b':
            if (cmd[1] == ' ' && isdigit(cmd[2])) {
               char *comma = strchr(cmd, ',');
               if (comma) {
                  /* break at pixel */
                  int x = atoi(cmd + 2);
                  int y = atoi(comma + 1);
                  if (NumBreakpoints < MAX_BREAKPOINTS) {
                     Breakpoints[NumBreakpoints].type = PIXEL;
                     Breakpoints[NumBreakpoints].x = x;
                     Breakpoints[NumBreakpoints].y = y;
                     Breakpoints[NumBreakpoints].enabled = GL_TRUE;
                     NumBreakpoints++;
                     printf("Breakpoint %d: break at pixel (%d, %d)\n",
                            NumBreakpoints, x, y);
                  }
               }
               else {
                  /* break at line */
                  int l = atoi(cmd + 2);
                  if (l && NumBreakpoints < MAX_BREAKPOINTS) {
                     Breakpoints[NumBreakpoints].type = LINE;
                     Breakpoints[NumBreakpoints].line = l;
                     Breakpoints[NumBreakpoints].enabled = GL_TRUE;
                     NumBreakpoints++;
                     printf("Breakpoint %d: break at line %d\n",
                            NumBreakpoints, l);
                  }
               }
            }
            else {
               /* list breakpoints */
               printf("Breakpoints:\n");
               for (i = 0; i < NumBreakpoints; i++) {
                  switch (Breakpoints[i].type) {
                  case LINE:
                     printf("  %d: break at line %d\n",
                            i + 1, Breakpoints[i].line);
                     break;
                  case PIXEL:
                     printf("  %d: break at pixel (%d, %d)\n",
                            i + 1, Breakpoints[i].x, Breakpoints[i].y);
                     break;
                  }
               }
            }
            break;
         case 'h':
            /* help */
            printf("Debugger commands:\n");
            printf("  b      list breakpoints\n");
            printf("  b N    break at line N\n");
            printf("  b x,y  break at pixel x,y\n");
            printf("  c      continue execution\n");
            printf("  d      display register values\n");
            printf("  h      help\n");
            printf("  l      list program\n");
            printf("  n      next instruction\n");
            printf("  p V    print value V\n");
            printf("  s N    skip N instructions\n");
            break;
         default:
            printf("Unknown command: %c\n", cmd[0]);
      }
   }
}