예제 #1
0
void GLGSRender::WriteDepthBuffer()
{
	if(!m_set_context_dma_z)
	{
		return;
	}

	// Reset the flag
	m_set_context_dma_z = false;

	u32 address = GetAddress(m_surface_offset_z, m_context_dma_z - 0xfeed0000);
	if(!Memory.IsGoodAddr(address))
	{
		ConLog.Warning("Bad depth address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_z, m_context_dma_z);
		return;
	}

	glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, &Memory[address]);
	checkForGlError("glReadPixels");

	glBindTexture(GL_TEXTURE_2D, g_depth_tex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RSXThread::m_width, RSXThread::m_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &Memory[address]);
	checkForGlError("glTexImage2D");
	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]);
	checkForGlError("glGetTexImage");
}
예제 #2
0
void Texture::load(){
	if(!loaded){
		if(channels == nullptr){
			channels = new int(0);
		}
		
				checkForGlError(0,__FILE__,__LINE__);
		glGenTextures(1, &textureId);
				checkForGlError(0,__FILE__,__LINE__);
		glBindTexture(GL_TEXTURE_2D, textureId);
				checkForGlError(0,__FILE__,__LINE__);

		unsigned char * tempData = nullptr;

		if(data != nullptr){
			tempData = data;
		}else{
			tempData = Resource::loadImage(src.c_str(), width, height, SOIL_LOAD_AUTO, channels);
			if(storeData){
				data = tempData;
			}
		}

		if(*channels == 3){
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, tempData);
		}else if(*channels == 4){
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tempData);
		}else{
			throw "Invalid number of image channels";
		}
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	
	NodeLoadable::load();
}
예제 #3
0
void GLGSRender::InitFragmentData()
{
	if(!m_cur_shader_prog)
	{
		ConLog.Error("InitFragmentData: m_cur_shader_prog == NULL");
		return;
	}

	for(u32 i=0; i<m_fragment_constants.size(); ++i)
	{
		const RSXTransformConstant& c = m_fragment_constants[i];

		u32 id = c.id - m_cur_shader_prog->offset;

		//ConLog.Warning("fc%u[0x%x - 0x%x] = (%f, %f, %f, %f)", id, c.id, m_cur_shader_prog->offset, c.x, c.y, c.z, c.w);

		const std::string name = fmt::Format("fc%u", id);
		const int l = m_program.GetLocation(name);
		checkForGlError("glGetUniformLocation " + name);

		glUniform4f(l, c.x, c.y, c.z, c.w);
		checkForGlError("glUniform4f " + name + fmt::Format(" %u [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
	}

	//if(m_fragment_constants.GetCount())
	//	ConLog.SkipLn();
}
예제 #4
0
void GLGSRender::InitVertexData()
{
	for(u32 i=0; i<m_transform_constants.GetCount(); ++i)
	{
		const RSXTransformConstant& c = m_transform_constants[i];
		const wxString name = wxString::Format("vc%u", c.id);
		const int l = m_program.GetLocation(name);
		checkForGlError("glGetUniformLocation " + name);

		//ConLog.Write(name + " x: %.02f y: %.02f z: %.02f w: %.02f", c.x, c.y, c.z, c.w);
		glUniform4f(l, c.x, c.y, c.z, c.w);
		checkForGlError("glUniform4f " + name + wxString::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
	}
}
예제 #5
0
void Texture::unload(){
	if(loaded){
		glDeleteTextures(1, &textureId);
		textureId = 0;
		checkForGlError(0,__FILE__,__LINE__);
		std::cout << loaded << " tex: " << this->src << std::endl;
	}
	
	NodeLoadable::unload();
}
예제 #6
0
void GLGSRender::WriteColourBufferD()
{
	if(!m_set_context_dma_color_d)
	{
		return;
	}

	u32 address = GetAddress(m_surface_offset_d, m_context_dma_color_d - 0xfeed0000);
	if(!Memory.IsGoodAddr(address))
	{
		ConLog.Warning("Bad colour buffer d address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_d, m_context_dma_color_d);
		return;
	}

	glReadBuffer(GL_COLOR_ATTACHMENT3);
	checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT3)");
	glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]);
	checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)");
}
예제 #7
0
void GLGSRender::DisableVertexData()
{
	m_vdata.clear();
	for(u32 i=0; i<m_vertex_count; ++i)
	{
		if(!m_vertex_data[i].IsEnabled() || !m_vertex_data[i].addr) continue;
		glDisableVertexAttribArray(i);
		checkForGlError("glDisableVertexAttribArray");
	}
	m_vao.Unbind();
}
예제 #8
0
void GLGSRender::InitFragmentData()
{
	if(!m_cur_shader_prog)
	{
		ConLog.Error("InitFragmentData: m_cur_shader_prog == NULL");
		return;
	}

	for(u32 i=0; i<m_fragment_constants.GetCount(); ++i)
	{
		const RSXTransformConstant& c = m_fragment_constants[i];

		u32 id = c.id - m_cur_shader_prog->offset + 2 * 4 * 4;

		const wxString name = wxString::Format("fc%u", id);
		const int l = m_program.GetLocation(name);
		checkForGlError("glGetUniformLocation " + name);

		//ConLog.Write(name + " x: %.02f y: %.02f z: %.02f w: %.02f", c.x, c.y, c.z, c.w);
		glUniform4f(l, c.x, c.y, c.z, c.w);
		checkForGlError("glUniform4f " + name + wxString::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
	}
}
예제 #9
0
void GLGSRender::InitVertexData()
{
	GLfloat scaleOffsetMat[16] = {1.0f, 0.0f, 0.0f, 0.0f, 
								  0.0f, 1.0f, 0.0f, 0.0f, 
								  0.0f, 0.0f, 1.0f, 0.0f, 
								  0.0f, 0.0f, 0.0f, 1.0f};
	int l;

	for(u32 i=0; i<m_transform_constants.size(); ++i)
	{
		const RSXTransformConstant& c = m_transform_constants[i];
		const std::string name = fmt::Format("vc[%u]", c.id);
		l = m_program.GetLocation(name);
		checkForGlError("glGetUniformLocation " + name);

		//ConLog.Write(name + " x: %.02f y: %.02f z: %.02f w: %.02f", c.x, c.y, c.z, c.w);
		glUniform4f(l, c.x, c.y, c.z, c.w);
		checkForGlError("glUniform4f " + name + fmt::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
	}

	// Scale
	scaleOffsetMat[0] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4 * 0)] / (RSXThread::m_width / RSXThread::m_width_scale);
	scaleOffsetMat[5] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4 * 1)] / (RSXThread::m_height / RSXThread::m_height_scale);
	scaleOffsetMat[10] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4*2)];

	// Offset
	scaleOffsetMat[3] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 0)] - (RSXThread::m_width / RSXThread::m_width_scale);
	scaleOffsetMat[7] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 1)] - (RSXThread::m_height / RSXThread::m_height_scale);
	scaleOffsetMat[11] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 2)];

	scaleOffsetMat[3] /= RSXThread::m_width / RSXThread::m_width_scale;
	scaleOffsetMat[7] /= RSXThread::m_height / RSXThread::m_height_scale;

	l = m_program.GetLocation("scaleOffsetMat");
	glUniformMatrix4fv(l, 1, false, scaleOffsetMat);
}
예제 #10
0
void GLGSRender::EnableVertexData(bool indexed_draw)
{
	static u32 offset_list[m_vertex_count];
	u32 cur_offset = 0;

	const u32 data_offset = indexed_draw ? 0 : m_draw_array_first;

	for(u32 i=0; i<m_vertex_count; ++i)
	{
		offset_list[i] = cur_offset;

		if(!m_vertex_data[i].IsEnabled() || !m_vertex_data[i].addr) continue;

		const size_t item_size = m_vertex_data[i].GetTypeSize() * m_vertex_data[i].size;
		const size_t data_size = m_vertex_data[i].data.size() - data_offset * item_size;
		const u32 pos = m_vdata.size();

		cur_offset += data_size;
		m_vdata.resize(m_vdata.size() + data_size);
		memcpy(&m_vdata[pos], &m_vertex_data[i].data[data_offset * item_size], data_size);
	}

	m_vao.Create();
	m_vao.Bind();
	checkForGlError("initializing vao");

	m_vbo.Create(indexed_draw ? 2 : 1);
	m_vbo.Bind(0);
	m_vbo.SetData(&m_vdata[0], m_vdata.size());

	if(indexed_draw)
	{
		m_vbo.Bind(GL_ELEMENT_ARRAY_BUFFER, 1);
		m_vbo.SetData(GL_ELEMENT_ARRAY_BUFFER, &m_indexed_array.m_data[0], m_indexed_array.m_data.size());
	}

	checkForGlError("initializing vbo");

#if	DUMP_VERTEX_DATA
	rFile dump("VertexDataArray.dump", rFile::write);
#endif

	for(u32 i=0; i<m_vertex_count; ++i)
	{
		if(!m_vertex_data[i].IsEnabled()) continue;

#if	DUMP_VERTEX_DATA
		dump.Write(wxString::Format("VertexData[%d]:\n", i));
		switch(m_vertex_data[i].type)
		{
		case CELL_GCM_VERTEX_S1:
			for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=2)
			{
				dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j]));
				if(!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n");
			}
		break;

		case CELL_GCM_VERTEX_F:
			for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=4)
			{
				dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j]));
				if(!(((j+4) / 4) % m_vertex_data[i].size)) dump.Write("\n");
			}
		break;

		case CELL_GCM_VERTEX_SF:
			for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=2)
			{
				dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j]));
				if(!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n");
			}
		break;

		case CELL_GCM_VERTEX_UB:
			for(u32 j = 0; j<m_vertex_data[i].data.size(); ++j)
			{
				dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j]));
				if(!((j+1) % m_vertex_data[i].size)) dump.Write("\n");
			}
		break;

		case CELL_GCM_VERTEX_S32K:
			for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=2)
			{
				dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j]));
				if(!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n");
			}
		break;
		
		// case CELL_GCM_VERTEX_CMP:
		
		case CELL_GCM_VERTEX_UB256:
			for(u32 j = 0; j<m_vertex_data[i].data.size(); ++j)
			{
				dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j]));
				if(!((j+1) % m_vertex_data[i].size)) dump.Write("\n");
			}
		break;

		default:
			ConLog.Error("Bad cv type! %d", m_vertex_data[i].type);
		return;
		}

		dump.Write("\n");
#endif

		static const u32 gl_types[] =
		{
			GL_SHORT,
			GL_FLOAT,
			GL_HALF_FLOAT,
			GL_UNSIGNED_BYTE,
			GL_SHORT,
			GL_UNSIGNED_BYTE,
		};

		static const bool gl_normalized[] =
		{
			true,
			false,
			false,
			true,
			false,
			false,
		};

		if(m_vertex_data[i].type >= 1 && m_vertex_data[i].type <= 7)
		{
			if(!m_vertex_data[i].addr)
			{
				switch(m_vertex_data[i].type)
				{
				case CELL_GCM_VERTEX_S32K:
				case CELL_GCM_VERTEX_S1:
					switch(m_vertex_data[i].size)
					{
					case 1: glVertexAttrib1s(i, (GLshort&)m_vertex_data[i].data[0]); break;
					case 2: glVertexAttrib2sv(i, (GLshort*)&m_vertex_data[i].data[0]); break;
					case 3: glVertexAttrib3sv(i, (GLshort*)&m_vertex_data[i].data[0]); break;
					case 4: glVertexAttrib4sv(i, (GLshort*)&m_vertex_data[i].data[0]); break;
					}
				break;

				case CELL_GCM_VERTEX_F:
					switch(m_vertex_data[i].size)
					{
					case 1: glVertexAttrib1f(i, (GLfloat&)m_vertex_data[i].data[0]); break;
					case 2: glVertexAttrib2fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break;
					case 3: glVertexAttrib3fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break;
					case 4: glVertexAttrib4fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break;
					}
				break;

				case CELL_GCM_VERTEX_CMP:
				case CELL_GCM_VERTEX_UB:
					glVertexAttrib4ubv(i, (GLubyte*)&m_vertex_data[i].data[0]);
				break;
				}

				checkForGlError("glVertexAttrib");
			}
			else
			{
				u32 gltype = gl_types[m_vertex_data[i].type - 1];
				bool normalized = gl_normalized[m_vertex_data[i].type - 1];

				glEnableVertexAttribArray(i);
				checkForGlError("glEnableVertexAttribArray");
				glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, (void*)offset_list[i]);
				checkForGlError("glVertexAttribPointer");
			}
		}
	}
}
예제 #11
0
void GLGSRender::ExecCMD()
{
	//return;
	if(!LoadProgram())
	{
		ConLog.Error("LoadProgram failed.");
		Emu.Pause();
		return;
	}

	if(!m_fbo.IsCreated() || RSXThread::m_width != last_width || RSXThread::m_height != last_height || last_depth_format != m_surface_depth_format)
	{
		ConLog.Warning("New FBO (%dx%d)", RSXThread::m_width, RSXThread::m_height);
		last_width = RSXThread::m_width;
		last_height = RSXThread::m_height;
		last_depth_format = m_surface_depth_format;

		m_fbo.Create();
		checkForGlError("m_fbo.Create");
		m_fbo.Bind();

		m_rbo.Create(4 + 1);
		checkForGlError("m_rbo.Create");

		for(int i=0; i<4; ++i)
		{
			m_rbo.Bind(i);
			m_rbo.Storage(GL_RGBA, RSXThread::m_width, RSXThread::m_height);
			checkForGlError("m_rbo.Storage(GL_RGBA)");
		}

		m_rbo.Bind(4);

		switch(m_surface_depth_format)
		{
		// case 0 found in BLJM60410-[Suzukaze no Melt - Days in the Sanctuary]  
		// [E : RSXThread]: Bad depth format! (0)
		// [E : RSXThread]: glEnable: opengl error 0x0506
		// [E : RSXThread]: glDrawArrays: opengl error 0x0506
		case 0:
			m_rbo.Storage(GL_DEPTH_COMPONENT, RSXThread::m_width, RSXThread::m_height);
			checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT)");
		break;
		
		case CELL_GCM_SURFACE_Z16:
			m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height);
			checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)");
		break;

		case CELL_GCM_SURFACE_Z24S8:
			m_rbo.Storage(GL_DEPTH24_STENCIL8, RSXThread::m_width, RSXThread::m_height);
			checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)");
		break;

		default:
			ConLog.Error("Bad depth format! (%d)", m_surface_depth_format);
			assert(0);
		break;
		}

		for(int i=0; i<4; ++i)
		{
			m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i));
			checkForGlError(fmt::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i));
		}

		m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4));
		checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)");

		if(m_surface_depth_format == 2)
		{
			m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4));
			checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)");
		}
	}

	if(!m_set_surface_clip_horizontal)
	{
		m_surface_clip_x = 0;
		m_surface_clip_w = RSXThread::m_width;
	}

	if(!m_set_surface_clip_vertical)
	{
		m_surface_clip_y = 0;
		m_surface_clip_h = RSXThread::m_height;
	}
		
	m_fbo.Bind();

	if(Ini.GSDumpDepthBuffer.GetValue())
		WriteDepthBuffer();

	static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };

	switch(m_surface_colour_target)
	{
	case CELL_GCM_SURFACE_TARGET_NONE:
		break;

	case CELL_GCM_SURFACE_TARGET_0:
		glDrawBuffer(draw_buffers[0]);
	break;

	case CELL_GCM_SURFACE_TARGET_1:
		glDrawBuffer(draw_buffers[1]);
	break;

	case CELL_GCM_SURFACE_TARGET_MRT1:
		glDrawBuffers(2, draw_buffers);
	break;

	case CELL_GCM_SURFACE_TARGET_MRT2:
		glDrawBuffers(3, draw_buffers);
	break;

	case CELL_GCM_SURFACE_TARGET_MRT3:
		glDrawBuffers(4, draw_buffers);
	break;

	default:
		ConLog.Error("Bad surface colour target: %d", m_surface_colour_target);
	break;
	}

	if(m_set_color_mask)
	{
		glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a);
		checkForGlError("glColorMask");
	}

	if(m_set_viewport_horizontal && m_set_viewport_vertical)
	{
		//glViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
		//checkForGlError("glViewport");
	}
	
	if (m_set_scissor_horizontal && m_set_scissor_vertical)
	{
		glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h);
		checkForGlError("glScissor");
	}
	
	if(m_clear_surface_mask)
	{
		GLbitfield f = 0;

		if (m_clear_surface_mask & 0x1)
		{
			glClearDepth(m_clear_surface_z / (float)0xffffff);

			f |= GL_DEPTH_BUFFER_BIT;
		}

		if (m_clear_surface_mask & 0x2)
		{
			glClearStencil(m_clear_surface_s);

			f |= GL_STENCIL_BUFFER_BIT;
		}

		if (m_clear_surface_mask & 0xF0)
		{
			glClearColor(
				m_clear_surface_color_r / 255.0f,
				m_clear_surface_color_g / 255.0f,
				m_clear_surface_color_b / 255.0f,
				m_clear_surface_color_a / 255.0f);

			f |= GL_COLOR_BUFFER_BIT;
		}

		glClear(f);
	}

	Enable(m_set_depth_test, GL_DEPTH_TEST);
	Enable(m_set_alpha_test, GL_ALPHA_TEST);
	Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT);
	Enable(m_set_blend, GL_BLEND);
	Enable(m_set_logic_op, GL_LOGIC_OP);
	Enable(m_set_cull_face, GL_CULL_FACE);
	Enable(m_set_dither, GL_DITHER);
	Enable(m_set_stencil_test, GL_STENCIL_TEST);
	Enable(m_set_line_smooth, GL_LINE_SMOOTH);
	Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH);
	Enable(m_set_point_sprite_control, GL_POINT_SPRITE);
	Enable(m_set_specular, GL_LIGHTING);
	Enable(m_set_poly_offset_fill, GL_POLYGON_OFFSET_FILL);
	Enable(m_set_poly_offset_line, GL_POLYGON_OFFSET_LINE);
	Enable(m_set_poly_offset_point, GL_POLYGON_OFFSET_POINT);
	Enable(m_set_restart_index, GL_PRIMITIVE_RESTART);
	Enable(m_set_line_stipple, GL_LINE_STIPPLE);

	if(m_set_clip_plane)
	{
		Enable(m_clip_plane_0, GL_CLIP_PLANE0);
		Enable(m_clip_plane_1, GL_CLIP_PLANE1);
		Enable(m_clip_plane_2, GL_CLIP_PLANE2);
		Enable(m_clip_plane_3, GL_CLIP_PLANE3);
		Enable(m_clip_plane_4, GL_CLIP_PLANE4);
		Enable(m_clip_plane_5, GL_CLIP_PLANE5);

		checkForGlError("m_set_clip_plane");
	}

	checkForGlError("glEnable");

	if (m_set_front_polygon_mode)
	{
		glPolygonMode(GL_FRONT, m_front_polygon_mode);
		checkForGlError("glPolygonMode(Front)");
	}

	if (m_set_back_polygon_mode)
	{
		glPolygonMode(GL_BACK, m_back_polygon_mode);
		checkForGlError("glPolygonMode(Back)");
	}

	if (m_set_point_size)
	{
		glPointSize(m_point_size);
		checkForGlError("glPointSize");
	}

	if (m_set_poly_offset_mode)
	{
		glPolygonOffset(m_poly_offset_scale_factor, m_poly_offset_bias);
		checkForGlError("glPolygonOffset");
	}

	if (m_set_logic_op)
	{
		glLogicOp(m_logic_op);
		checkForGlError("glLogicOp");
	}

	if(m_set_two_sided_stencil_test_enable)
	{
		if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
		{
			glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
			checkForGlError("glStencilOpSeparate");
		}

		if(m_set_stencil_mask)
		{
			glStencilMaskSeparate(GL_FRONT, m_stencil_mask);
			checkForGlError("glStencilMaskSeparate");
		}

		if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
		{
			glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
			checkForGlError("glStencilFuncSeparate");
		}

		if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass)
		{
			glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass);
			checkForGlError("glStencilOpSeparate(GL_BACK)");
		}

		if(m_set_back_stencil_mask)
		{
			glStencilMaskSeparate(GL_BACK, m_back_stencil_mask);
			checkForGlError("glStencilMaskSeparate(GL_BACK)");
		}

		if(m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask)
		{
			glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask);
			checkForGlError("glStencilFuncSeparate(GL_BACK)");
		}
	}
	else
	{
		if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
		{
			glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
			checkForGlError("glStencilOp");
		}

		if(m_set_stencil_mask)
		{
			glStencilMask(m_stencil_mask);
			checkForGlError("glStencilMask");
		}

		if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
		{
			glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
			checkForGlError("glStencilFunc");
		}
	}

	if(m_set_shade_mode)
	{
		glShadeModel(m_shade_mode);
		checkForGlError("glShadeModel");
	}

	if(m_set_depth_mask)
	{
		glDepthMask(m_depth_mask);
		checkForGlError("glDepthMask");
	}

	if(m_set_depth_func)
	{
		//ConLog.Warning("glDepthFunc(0x%x)", m_depth_func);
		glDepthFunc(m_depth_func);
		checkForGlError("glDepthFunc");
	}

	if(m_set_depth_bounds)
	{
		//ConLog.Warning("glDepthBounds(%f, %f)", m_depth_bounds_min, m_depth_bounds_max);
		glDepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max);
		checkForGlError("glDepthBounds");
	}

	if(m_set_clip)
	{
		//ConLog.Warning("glDepthRangef(%f, %f)", m_clip_min, m_clip_max);
		glDepthRangef(m_clip_min, m_clip_max);
		checkForGlError("glDepthRangef");
	}

	if(m_set_line_width)
	{
		glLineWidth(m_line_width);
		checkForGlError("glLineWidth");
	}

	if (m_set_line_stipple)
	{
		glLineStipple(m_line_stipple_factor, m_line_stipple_pattern);
		checkForGlError("glLineStipple");
	}

	if(m_set_blend_equation)
	{
		glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha);
		checkForGlError("glBlendEquationSeparate");
	}

	if(m_set_blend_sfactor && m_set_blend_dfactor)
	{
		glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha);
		checkForGlError("glBlendFuncSeparate");
	}

	if(m_set_blend_color)
	{
		glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a);
		checkForGlError("glBlendColor");
	}

	if(m_set_cull_face)
	{
		glCullFace(m_cull_face);
		checkForGlError("glCullFace");
	}

	if (m_set_front_face)
	{
		glFrontFace(m_front_face);
		checkForGlError("glFrontFace");
	}

	if(m_set_alpha_func && m_set_alpha_ref)
	{
		glAlphaFunc(m_alpha_func, m_alpha_ref);
		checkForGlError("glAlphaFunc");
	}

	if(m_set_fog_mode)
	{
		glFogi(GL_FOG_MODE, m_fog_mode);
		checkForGlError("glFogi(GL_FOG_MODE)");
	}

	if(m_set_fog_params)
	{
		glFogf(GL_FOG_START, m_fog_param0);
		checkForGlError("glFogf(GL_FOG_START)");
		glFogf(GL_FOG_END, m_fog_param1);
		checkForGlError("glFogf(GL_FOG_END)");
	}

	if(m_set_restart_index)
	{
		glPrimitiveRestartIndex(m_restart_index);
		checkForGlError("glPrimitiveRestartIndex");
	}

	if(m_indexed_array.m_count && m_draw_array_count)
	{
		ConLog.Warning("m_indexed_array.m_count && draw_array_count");
	}

	for(u32 i=0; i<m_textures_count; ++i)
	{
		if(!m_textures[i].IsEnabled()) continue;

		glActiveTexture(GL_TEXTURE0 + i);
		checkForGlError("glActiveTexture");
		m_gl_textures[i].Create();
		m_gl_textures[i].Bind();
		checkForGlError(fmt::Format("m_gl_textures[%d].Bind", i));
		m_program.SetTex(i);
		m_gl_textures[i].Init(m_textures[i]);
		checkForGlError(fmt::Format("m_gl_textures[%d].Init", i));
	}

	m_vao.Bind();
	if(m_indexed_array.m_count)
	{
		LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
	}

	EnableVertexData(m_indexed_array.m_count ? true : false);

	InitVertexData();
	InitFragmentData();

	if(m_indexed_array.m_count)
	{
		switch(m_indexed_array.m_type)
		{
		case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
			glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr);
			checkForGlError("glDrawElements #4");
		break;

		case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
			glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr);
			checkForGlError("glDrawElements #2");
		break;

		default:
			ConLog.Error("Bad indexed array type (%d)", m_indexed_array.m_type);
		break;
		}

		DisableVertexData();
		m_indexed_array.Reset();
	}

	if(m_draw_array_count)
	{
		//ConLog.Warning("glDrawArrays(%d,%d,%d)", m_draw_mode - 1, m_draw_array_first, m_draw_array_count);
		glDrawArrays(m_draw_mode - 1, 0, m_draw_array_count);
		checkForGlError("glDrawArrays");
		DisableVertexData();
	}

	if (Ini.GSDumpColorBuffers.GetValue())
	{
		WriteColorBuffers();
	}
}
예제 #12
0
bool GLGSRender::LoadProgram()
{
	if(!m_cur_shader_prog)
	{
		ConLog.Warning("LoadProgram: m_cur_shader_prog == NULL");
		return false;
	}

	if(!m_cur_vertex_prog)
	{
		ConLog.Warning("LoadProgram: m_cur_vertex_prog == NULL");
		return false;
	}

	m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog, m_shader_prog);
	m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog);

	//ConLog.Write("Create program");

	if(m_fp_buf_num == -1)
	{
		ConLog.Warning("FP not found in buffer!");
		m_shader_prog.DecompileAsync(*m_cur_shader_prog);
		m_shader_prog.Wait();
		m_shader_prog.Compile();
		checkForGlError("m_shader_prog.Compile");

		rFile f(rGetCwd() + "/FragmentProgram.txt", rFile::write);
		f.Write(m_shader_prog.GetShaderText());
	}

	if(m_vp_buf_num == -1)
	{
		ConLog.Warning("VP not found in buffer!");
		m_vertex_prog.DecompileAsync(*m_cur_vertex_prog);
		m_vertex_prog.Wait();
		m_vertex_prog.Compile();
		checkForGlError("m_vertex_prog.Compile");

		rFile f(rGetCwd() + "/VertexProgram.txt", rFile::write);
		f.Write(m_vertex_prog.shader);
	}

	if(m_fp_buf_num != -1 && m_vp_buf_num != -1)
	{
		m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num);
	}

	if(m_program.id)
	{
		// RSX Debugger: Check if this program was modified and update it
		if (Ini.GSLogPrograms.GetValue())
		{
			for(auto& program : m_debug_programs)
			{
				if (program.id == m_program.id && program.modified)
				{
					// TODO: This isn't working perfectly. Is there any better/shorter way to update the program
					m_vertex_prog.shader = program.vp_shader;
					m_shader_prog.SetShaderText(program.fp_shader);
					m_vertex_prog.Wait();
					m_vertex_prog.Compile();
					checkForGlError("m_vertex_prog.Compile");
					m_shader_prog.Wait();
					m_shader_prog.Compile();
					checkForGlError("m_shader_prog.Compile");
					glAttachShader(m_program.id, m_vertex_prog.id);
					glAttachShader(m_program.id, m_shader_prog.GetId());
					glLinkProgram(m_program.id);
					checkForGlError("glLinkProgram");
					glDetachShader(m_program.id, m_vertex_prog.id);
					glDetachShader(m_program.id, m_shader_prog.GetId());
					program.vp_id = m_vertex_prog.id;
					program.fp_id = m_shader_prog.GetId();
					program.modified = false;
				}
			}
		}
		m_program.Use();
	}
	else
	{
		m_program.Create(m_vertex_prog.id, m_shader_prog.GetId());
		checkForGlError("m_program.Create");
		m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_shader_prog, m_vertex_prog, *m_cur_vertex_prog);
		checkForGlError("m_prog_buffer.Add");
		m_program.Use();

		// RSX Debugger
		if (Ini.GSLogPrograms.GetValue())
		{
			RSXDebuggerProgram program;
			program.id = m_program.id;
			program.vp_id = m_vertex_prog.id;
			program.fp_id = m_shader_prog.GetId();
			program.vp_shader = m_vertex_prog.shader;
			program.fp_shader = m_shader_prog.GetShaderText();
			m_debug_programs.push_back(program);
		}
	}

	return true;
}
예제 #13
0
void GLGSRender::Flip()
{
	// Set scissor to FBO size 
	if (m_set_scissor_horizontal && m_set_scissor_vertical)
	{
		glScissor(0, 0, RSXThread::m_width, RSXThread::m_height);
		checkForGlError("glScissor");
	}
	
	switch (m_surface_colour_target)
	{
	case CELL_GCM_SURFACE_TARGET_0:
	case CELL_GCM_SURFACE_TARGET_1:
	{
		// Fast path for non-MRT using glBlitFramebuffer.
		GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
		// Renderbuffer is upside turn , swapped srcY0 and srcY1
		GLfbo::Blit(0, RSXThread::m_height, RSXThread::m_width, 0, 0, 0, RSXThread::m_width, RSXThread::m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
	}
	break;

	case CELL_GCM_SURFACE_TARGET_NONE:
	case CELL_GCM_SURFACE_TARGET_MRT1:
	case CELL_GCM_SURFACE_TARGET_MRT2:
	case CELL_GCM_SURFACE_TARGET_MRT3:
	{
		// Slow path for MRT/None target using glReadPixels.
		static u8* src_buffer = nullptr;
		static u32 width = 0;
		static u32 height = 0;
		GLenum format = GL_RGBA;

		if (m_read_buffer)
		{
			format = GL_BGRA;
			gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr);
			u32 addr = GetAddress(re(buffers[m_gcm_current_buffer].offset), CELL_GCM_LOCATION_LOCAL);

			if (Memory.IsGoodAddr(addr))
			{
				width = re(buffers[m_gcm_current_buffer].width);
				height = re(buffers[m_gcm_current_buffer].height);
				src_buffer = (u8*)Memory.VirtualToRealAddr(addr);
			}
			else
			{
				src_buffer = nullptr;
			}
		}
		else if (m_fbo.IsCreated())
		{
			format = GL_RGBA;
			static std::vector<u8> pixels;
			pixels.resize(RSXThread::m_width * RSXThread::m_height * 4);
			m_fbo.Bind(GL_READ_FRAMEBUFFER);
			glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, pixels.data());

			src_buffer = pixels.data();
			width = RSXThread::m_width;
			height = RSXThread::m_height;
		}
		else
			src_buffer = nullptr;

		if (src_buffer)
		{
			glDisable(GL_STENCIL_TEST);
			glDisable(GL_DEPTH_TEST);
			glDisable(GL_CLIP_PLANE0);
			glDisable(GL_CLIP_PLANE1);
			glDisable(GL_CLIP_PLANE2);
			glDisable(GL_CLIP_PLANE3);
			glDisable(GL_CLIP_PLANE4);
			glDisable(GL_CLIP_PLANE5);
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, g_flip_tex);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			glOrtho(0, 1, 0, 1, 0, 1);
			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();

			GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);

			m_program.UnUse();
			m_program.Use();
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);

			glColor3f(1, 1, 1);
			glBegin(GL_QUADS);
			glTexCoord2i(0, 1);
			glVertex2i(0, 0);

			glTexCoord2i(1, 1);
			glVertex2i(1, 0);

			glTexCoord2i(1, 0);
			glVertex2i(1, 1);

			glTexCoord2i(0, 0);
			glVertex2i(0, 1);
			glEnd();
		}
	}
	break;
	}

	// Draw Objects
	for (uint i = 0; i<m_post_draw_objs.size(); ++i)
	{
		m_post_draw_objs[i].Draw();
	}

	m_frame->Flip(m_context);
	
	// Restore scissor
	if (m_set_scissor_horizontal && m_set_scissor_vertical)
	{
		glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h);
		checkForGlError("glScissor");
	}

}
예제 #14
0
bool GLGSRender::LoadProgram()
{
	if(!m_cur_shader_prog)
	{
		ConLog.Warning("LoadProgram: m_cur_shader_prog == NULL");

		return false;
	}

	m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog, m_shader_prog);

	if(m_fp_buf_num == -1) m_shader_prog.Decompile(*m_cur_shader_prog);

	if(!m_cur_vertex_prog)
	{
		ConLog.Warning("LoadProgram: m_cur_vertex_prog == NULL");

		return false;
	}

	//ConLog.Write("Create program");
	m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog);

	if(m_vp_buf_num == -1) 
	{
		ConLog.Warning("VP not found in buffer!");
		m_vertex_prog.Decompile(*m_cur_vertex_prog);
	}

	if(m_fp_buf_num == -1)
	{
		ConLog.Warning("FP not found in buffer!");
		m_shader_prog.Wait();
		m_shader_prog.Compile();
		checkForGlError("m_shader_prog.Compile");

		wxFile f(wxGetCwd() + "/FragmentProgram.txt", wxFile::write);
		f.Write(m_shader_prog.shader);
	}

	if(m_vp_buf_num == -1)
	{
		m_vertex_prog.Wait();
		m_vertex_prog.Compile();
		checkForGlError("m_vertex_prog.Compile");

		wxFile f(wxGetCwd() + "/VertexProgram.txt", wxFile::write);
		f.Write(m_vertex_prog.shader);
	}

	if(m_fp_buf_num != -1 && m_vp_buf_num != -1)
	{
		m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num);
	}

	if(m_program.id)
	{
		m_program.Use();
	}
	else
	{
		m_program.Create(m_vertex_prog.id, m_shader_prog.id);
		checkForGlError("m_program.Create");
		m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_shader_prog, m_vertex_prog, *m_cur_vertex_prog);
		checkForGlError("m_prog_buffer.Add");
		m_program.Use();

		GLint r = GL_FALSE;
		glGetProgramiv(m_program.id, GL_VALIDATE_STATUS, &r);
		if(r != GL_TRUE)
		{
			glGetProgramiv(m_program.id, GL_INFO_LOG_LENGTH, &r);

			if(r)
			{
				char* buf = new char[r+1];
				GLsizei len;
				memset(buf, 0, r+1);
				glGetProgramInfoLog(m_program.id, r, &len, buf);
				ConLog.Error("Failed to validate program: %s", buf);
				delete[] buf;
			}

			Emu.Pause();
		}
	}

	return true;
}
예제 #15
0
void GLGSRender::ExecCMD()
{
	if(!LoadProgram())
	{
		ConLog.Error("LoadProgram failed.");
		Emu.Pause();
		return;
	}

	if(!m_fbo.IsCreated() || m_width != last_width || m_height != last_height || last_depth_format != m_surface_depth_format)
	{
		ConLog.Warning("New FBO (%dx%d)", m_width, m_height);
		last_width = m_width;
		last_height = m_height;
		last_depth_format = m_surface_depth_format;

		m_fbo.Create();
		checkForGlError("m_fbo.Create");
		m_fbo.Bind();

		m_rbo.Create(4 + 1);
		checkForGlError("m_rbo.Create");

		for(int i=0; i<4; ++i)
		{
			m_rbo.Bind(i);
			m_rbo.Storage(GL_RGBA, m_width, m_height);
			checkForGlError("m_rbo.Storage(GL_RGBA)");
		}

		m_rbo.Bind(4);

		switch(m_surface_depth_format)
		{
		case 1:
			m_rbo.Storage(GL_DEPTH_COMPONENT16, m_width, m_height);
			checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)");
		break;

		case 2:
			m_rbo.Storage(GL_DEPTH24_STENCIL8, m_width, m_height);
			checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)");
		break;

		default:
			ConLog.Error("Bad depth format! (%d)", m_surface_depth_format);
			assert(0);
		break;
		}

		for(int i=0; i<4; ++i)
		{
			m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i));
			checkForGlError(wxString::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i));
		}

		m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4));
		checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)");

		if(m_surface_depth_format == 2)
		{
			m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4));
			checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)");
		}
	}

	if(!m_set_surface_clip_horizontal)
	{
		m_surface_clip_x = 0;
		m_surface_clip_w = m_width;
	}

	if(!m_set_surface_clip_vertical)
	{
		m_surface_clip_y = 0;
		m_surface_clip_h = m_height;
	}
		
	m_fbo.Bind();
	if(Ini.GSDumpDepthBuffer.GetValue())
		WriteDepthBuffer();
	static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };

	switch(m_surface_colour_target)
	{
	case 0x0:
		break;

	case 0x1:
		glDrawBuffer(draw_buffers[0]);
	break;

	case 0x2:
		glDrawBuffer(draw_buffers[1]);
	break;

	case 0x13:
		glDrawBuffers(2, draw_buffers);
	break;

	case 0x17:
		glDrawBuffers(3, draw_buffers);
	break;

	case 0x1f:
		glDrawBuffers(4, draw_buffers);
	break;

	default:
		ConLog.Error("Bad surface colour target: %d", m_surface_colour_target);
	break;
	}

	if(m_set_color_mask)
	{
		glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a);
		checkForGlError("glColorMask");
	}

	if(m_set_viewport_horizontal && m_set_viewport_vertical)
	{
		glViewport(m_viewport_x, m_height-m_viewport_y-m_viewport_h, m_viewport_w, m_viewport_h);
		checkForGlError("glViewport");
	}

	if(m_set_scissor_horizontal && m_set_scissor_vertical)
	{
		glScissor(m_scissor_x, m_height-m_scissor_y-m_scissor_h, m_scissor_w, m_scissor_h);
		checkForGlError("glScissor");
	}

	if(m_clear_surface_mask)
	{
		GLbitfield f = 0;

		if (m_clear_surface_mask & 0x1)
		{
			glClearDepth(m_clear_surface_z / (float)0xffffff);

			f |= GL_DEPTH_BUFFER_BIT;
		}

		if (m_clear_surface_mask & 0x2)
		{
			glClearStencil(m_clear_surface_s);

			f |= GL_STENCIL_BUFFER_BIT;
		}

		if (m_clear_surface_mask & 0xF0)
		{
			glClearColor(
				m_clear_surface_color_r / 255.0f,
				m_clear_surface_color_g / 255.0f,
				m_clear_surface_color_b / 255.0f,
				m_clear_surface_color_a / 255.0f);

			f |= GL_COLOR_BUFFER_BIT;
		}

		glClear(f);
	}

	if(m_set_front_polygon_mode)
	{
		glPolygonMode(GL_FRONT, m_front_polygon_mode);
		checkForGlError("glPolygonMode");
	}

	Enable(m_depth_test_enable, GL_DEPTH_TEST);
	Enable(m_set_alpha_test, GL_ALPHA_TEST);
	Enable(m_set_depth_bounds_test, GL_DEPTH_CLAMP);
	Enable(m_set_blend, GL_BLEND);
	Enable(m_set_logic_op, GL_LOGIC_OP);
	Enable(m_set_cull_face_enable, GL_CULL_FACE);
	Enable(m_set_dither, GL_DITHER);
	Enable(m_set_stencil_test, GL_STENCIL_TEST);
	Enable(m_set_line_smooth, GL_LINE_SMOOTH);
	Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH);

	if(m_set_clip_plane)
	{
		Enable(m_clip_plane_0, GL_CLIP_PLANE0);
		Enable(m_clip_plane_1, GL_CLIP_PLANE1);
		Enable(m_clip_plane_2, GL_CLIP_PLANE2);
		Enable(m_clip_plane_3, GL_CLIP_PLANE3);
		Enable(m_clip_plane_4, GL_CLIP_PLANE4);
		Enable(m_clip_plane_5, GL_CLIP_PLANE5);

		checkForGlError("m_set_clip_plane");
	}

	checkForGlError("glEnable");

	if(m_set_two_sided_stencil_test_enable)
	{
		if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
		{
			glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
			checkForGlError("glStencilOpSeparate");
		}

		if(m_set_stencil_mask)
		{
			glStencilMaskSeparate(GL_FRONT, m_stencil_mask);
			checkForGlError("glStencilMaskSeparate");
		}

		if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
		{
			glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
			checkForGlError("glStencilFuncSeparate");
		}

		if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass)
		{
			glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass);
			checkForGlError("glStencilOpSeparate(GL_BACK)");
		}

		if(m_set_back_stencil_mask)
		{
			glStencilMaskSeparate(GL_BACK, m_back_stencil_mask);
			checkForGlError("glStencilMaskSeparate(GL_BACK)");
		}

		if(m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask)
		{
			glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask);
			checkForGlError("glStencilFuncSeparate(GL_BACK)");
		}
	}
	else
	{
		if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
		{
			glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
			checkForGlError("glStencilOp");
		}

		if(m_set_stencil_mask)
		{
			glStencilMask(m_stencil_mask);
			checkForGlError("glStencilMask");
		}

		if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
		{
			glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
			checkForGlError("glStencilFunc");
		}
	}

	if(m_set_shade_mode)
	{
		glShadeModel(m_shade_mode);
		checkForGlError("glShadeModel");
	}

	if(m_set_depth_mask)
	{
		glDepthMask(m_depth_mask);
		checkForGlError("glDepthMask");
	}

	if(m_set_depth_func)
	{
		glDepthFunc(m_depth_func);
		checkForGlError("glDepthFunc");
	}

	if(m_set_clip)
	{
		glDepthRangef(m_clip_min, m_clip_max);
		checkForGlError("glDepthRangef");
	}

	if(m_set_line_width)
	{
		glLineWidth(m_line_width / 255.f);
		checkForGlError("glLineWidth");
	}

	if(m_set_blend_equation)
	{
		glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha);
		checkForGlError("glBlendEquationSeparate");
	}

	if(m_set_blend_sfactor && m_set_blend_dfactor)
	{
		glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha);
		checkForGlError("glBlendFuncSeparate");
	}

	if(m_set_blend_color)
	{
		glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a);
		checkForGlError("glBlendColor");
	}

	if(m_set_cull_face)
	{
		glCullFace(m_cull_face);
		checkForGlError("glCullFace");
	}

	if(m_set_alpha_func && m_set_alpha_ref)
	{
		glAlphaFunc(m_alpha_func, m_alpha_ref);
		checkForGlError("glAlphaFunc");
	}

	if(m_set_fog_mode)
	{
		glFogi(GL_FOG_MODE, m_fog_mode);
		checkForGlError("glFogi(GL_FOG_MODE)");
	}

	if(m_set_fog_params)
	{
		glFogf(GL_FOG_START, m_fog_param0);
		checkForGlError("glFogf(GL_FOG_START)");
		glFogf(GL_FOG_END, m_fog_param1);
		checkForGlError("glFogf(GL_FOG_END)");
	}

	if(m_indexed_array.m_count && m_draw_array_count)
	{
		ConLog.Warning("m_indexed_array.m_count && draw_array_count");
	}

	for(u32 i=0; i<m_textures_count; ++i)
	{
		if(!m_textures[i].IsEnabled()) continue;

		glActiveTexture(GL_TEXTURE0 + i);
		checkForGlError("glActiveTexture");
		m_gl_textures[i].Create();
		m_gl_textures[i].Bind();
		checkForGlError(wxString::Format("m_gl_textures[%d].Bind", i));
		m_program.SetTex(i);
		m_gl_textures[i].Init(m_textures[i]);
		checkForGlError(wxString::Format("m_gl_textures[%d].Init", i));
	}

	m_vao.Bind();
	if(m_indexed_array.m_count)
	{
		LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
	}

	EnableVertexData(m_indexed_array.m_count ? true : false);

	InitVertexData();
	InitFragmentData();

	if(m_indexed_array.m_count)
	{
		switch(m_indexed_array.m_type)
		{
		case 0:
			glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr);
			checkForGlError("glDrawElements #4");
		break;

		case 1:
			glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr);
			checkForGlError("glDrawElements #2");
		break;

		default:
			ConLog.Error("Bad indexed array type (%d)", m_indexed_array.m_type);
		break;
		}

		DisableVertexData();
		m_indexed_array.Reset();
	}

	if(m_draw_array_count)
	{
		glDrawArrays(m_draw_mode - 1, 0, m_draw_array_count);
		checkForGlError("glDrawArrays");
		DisableVertexData();
		m_draw_array_count = 0;
	}

	if(Ini.GSDumpColorBuffers.GetValue())
		WriteBuffers();
}
예제 #16
0
bool GLGSRender::LoadProgram()
{
	if(!m_cur_shader_prog)
	{
		ConLog.Warning("LoadProgram: m_cur_shader_prog == NULL");

		return false;
	}

	m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog, m_shader_prog);

	if(m_fp_buf_num == -1) m_shader_prog.Decompile(*m_cur_shader_prog);

	if(!m_cur_vertex_prog)
	{
		ConLog.Warning("LoadProgram: m_cur_vertex_prog == NULL");

		return false;
	}

	//ConLog.Write("Create program");
	m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog);

	if(m_vp_buf_num == -1) 
	{
		ConLog.Warning("VP not found in buffer!");
		m_vertex_prog.Decompile(*m_cur_vertex_prog);
	}

	if(m_fp_buf_num == -1)
	{
		ConLog.Warning("FP not found in buffer!");
		m_shader_prog.Wait();
		m_shader_prog.Compile();
		checkForGlError("m_shader_prog.Compile");

		wxFile f(wxGetCwd() + "/FragmentProgram.txt", wxFile::write);
		f.Write(m_shader_prog.shader);
	}

	if(m_vp_buf_num == -1)
	{
		m_vertex_prog.Wait();
		m_vertex_prog.Compile();
		checkForGlError("m_vertex_prog.Compile");

		wxFile f(wxGetCwd() + "/VertexProgram.txt", wxFile::write);
		f.Write(m_vertex_prog.shader);
	}

	if(m_fp_buf_num != -1 && m_vp_buf_num != -1)
	{
		m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num);
	}

	if(m_program.id)
	{
		m_program.Use();
	}
	else
	{
		m_program.Create(m_vertex_prog.id, m_shader_prog.id);
		checkForGlError("m_program.Create");
		m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_shader_prog, m_vertex_prog, *m_cur_vertex_prog);
		checkForGlError("m_prog_buffer.Add");
		m_program.Use();
	}

	return true;
}