<commit_before>#include "ShaderNew.h"
#include "DynamicTexture.h"

#include <GL/GLee.h>
#include <stdio.h>

namespace d2d
{

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

static const int ATTRIB_VERTEX    = 0;
static const int ATTRIB_TEXTCOORD = 1;
static const int ATTRIB_COLOR     = 2;
static const int ATTRIB_ADDITIVE  = 3;

ShaderNew* ShaderNew::m_instance = NULL;

ShaderNew* ShaderNew::Instance()
{
	if (!m_instance)
	{
		m_instance = new ShaderNew();
		m_instance->load();
	}
	return m_instance;
}

ShaderNew::ShaderNew()
{
	m_prog_curr = 0;
	m_prog_sprite = 0;
	m_prog_shape = 0;

	VertexBuffer = IndexBuffer = 0;
	m_sprite_count = 0;
	m_vb = NULL;
	m_tex = 0;
	m_fbo = 0;

	m_color = 0xffffffff;
	m_additive = 0;
}

void ShaderNew::SetSpriteColor(const Colorf& multi, const Colorf& add)
{
	// ABGR
	m_color = ((int)(multi.a * 255 + 0.5f) << 24) |
		((int)(multi.b * 255 + 0.5f) << 16) |
		((int)(multi.g * 255 + 0.5f) << 8) |
		((int)(multi.r * 255 + 0.5f));
	m_additive = ((int)(add.a * 255 + 0.5f) << 24) |
		((int)(add.b * 255 + 0.5f) << 16) |
		((int)(add.g * 255 + 0.5f) << 8) |
		((int)(add.r * 255 + 0.5f));
}

void ShaderNew::SetShapeColor(const Colorf& col)
{
	if (m_prog_curr == m_prog_shape) {
		glUniform4fv(m_col_loc, 1, (GLfloat*)(&col.r));
	}
}

void ShaderNew::sprite()
{
	if (m_prog_curr != m_prog_sprite) {
		Commit();

		glEnable(GL_BLEND);

		// todo Դejoy2dõGL_ONE
		//		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glUseProgram(m_prog_sprite);
		m_prog_curr = m_prog_sprite;
	}
}

void ShaderNew::shape()
{
	if (m_prog_curr != m_prog_shape) {
		Commit();

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glUseProgram(m_prog_shape);
		m_prog_curr = m_prog_shape;
	}
}

void ShaderNew::null()
{
	Commit();

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glUseProgram(0);
	m_prog_curr = 0;
}

void ShaderNew::release()
{
	unload();
}

void ShaderNew::reload()
{
	load();
}

void ShaderNew::SetTexture(int tex)
{
	if (m_tex != tex)
	{
		Commit();
		m_tex = (GLuint)tex;
		glBindTexture(GL_TEXTURE_2D, m_tex);
	}
}

void ShaderNew::SetFBO(int fbo)
{
	if (m_fbo != fbo)
	{
		Commit();
		m_fbo = (GLuint)fbo;
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
	}
}

void ShaderNew::Draw(const float vb[16], int texid)
{
	if (m_fbo == 1) {
		int zz = 0;
	}

	SetTexture(texid);

	CopyVertex(vb);
	if (++m_sprite_count >= MAX_COMMBINE) {
		Commit();
	}
}

void ShaderNew::Flush()
{
	Commit();

	DynamicTexture::Instance()->DebugDraw();
}

void ShaderNew::load()
{
#if 0
	#define FLOAT_PRECISION \
	"#ifdef GL_FRAGMENT_PRECISION_HIGH  \n" \
	"precision highp float;  \n" \
	"#else  \n" \
	"precision lowp float;  \n" \
	"#endif  \n"
#else
	#define FLOAT_PRECISION \
	"precision lowp float;  \n"
#endif

	static const char * sprite_vs =
		FLOAT_PRECISION
		"attribute vec4 position;  \n"
		"attribute vec2 texcoord;  \n"
		"attribute vec4 color;     \n"
		"attribute vec4 additive;  \n"
		"\n"
		"varying vec2 v_texcoord;  \n"
		"varying vec4 v_fragmentColor;  \n"
		"varying vec4 v_fragmentAddi; \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  gl_Position = position; "
 		"  v_fragmentColor = color / 255.0; \n"
 		"  v_fragmentAddi = additive / 255.0; \n"
		"  v_texcoord = texcoord;  \n"
		"}  \n"
		;

	static const char * sprite_fs =
		FLOAT_PRECISION
		"varying vec4 v_fragmentColor; \n"
		"varying vec4 v_fragmentAddi; \n"
		"varying vec2 v_texcoord;  \n"
		"uniform sampler2D texture0;  \n"
		"\n"
		"void main()  \n"
		"{  \n"
  		"  vec4 tmp = texture2D(texture0, v_texcoord);  \n"
  		"  gl_FragColor.xyz = tmp.xyz * v_fragmentColor.xyz;  \n"
  		"  gl_FragColor.w = tmp.w;    \n"
  		"  gl_FragColor *= v_fragmentColor.w;  \n"
  		"  gl_FragColor.xyz += v_fragmentAddi.xyz * tmp.w;  \n"
		"}  \n"
		;

	static const char* font_fs =
		FLOAT_PRECISION
		"varying vec4 v_fragmentColor; \n"
		"varying vec2 v_texcoord;  \n"
		"uniform sampler2D texture0;  \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  float mask = texture2D(texture0, v_texcoord).a;    \n"
		"  vec4 clr;                                          \n"
		"  clr.rgb = vec3(1.0, 0.0, 0.0);                     \n"
		"  if (mask < 0.5)				                      \n"
		"    clr.a = 0.0;                                     \n"
		"  else                                               \n"
		"    clr.a = 1.0;                                     \n"
		"  gl_FragColor = clr;                                \n"
		"}  \n"
		;

	static const char * shape_vs =
		FLOAT_PRECISION
		"uniform vec4 color;     \n"
		"\n"
		"varying vec4 v_fragmentColor;  \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; "
		"  v_fragmentColor = color; \n"
		"}  \n"
		;

	static const char * shape_fs =
		FLOAT_PRECISION
		"varying vec4 v_fragmentColor; \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  gl_FragColor = v_fragmentColor;"
		"}  \n"
		;

	glEnable(GL_BLEND);
	// todo Դejoy2dõGL_ONE
	//glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	m_prog_sprite = InitShader(sprite_fs, sprite_vs);
	m_prog_shape = InitShader(shape_fs, shape_vs);
	m_prog_font = InitShader(font_fs, sprite_vs);

	InitBuffers();

	// bind attr
	m_col_loc = glGetUniformLocation(m_prog_shape, "color");

	m_vb = new float[SPRITE_FLOAT_NUM * MAX_COMMBINE];
}

void ShaderNew::unload()
{
// 	delete m_instance;
// 	m_instance = NULL;

	// todo others
	glDeleteBuffers(1, &VertexBuffer);
	glDeleteBuffers(1, &IndexBuffer);

	delete[] m_vb;
	m_vb = NULL;
}

int ShaderNew::InitShader(const char *FS, const char *VS)
{
	GLuint prog = glCreateProgram();

	GLuint fs = CompileShader(FS, GL_FRAGMENT_SHADER);
	if (fs == 0) {
		return 0;
	} else {
		glAttachShader(prog, fs);
	}

	GLuint vs = CompileShader(VS, GL_VERTEX_SHADER);
	if (vs == 0) {
		return 0;
	} else {
		glAttachShader(prog, vs);
	}

 	// attr location
 	glBindAttribLocation(prog, ATTRIB_VERTEX, "position");
 	glBindAttribLocation(prog, ATTRIB_TEXTCOORD, "texcoord");
 	glBindAttribLocation(prog, ATTRIB_COLOR, "color");
 	glBindAttribLocation(prog, ATTRIB_ADDITIVE, "additive");

	// link
	GLint status;
	glLinkProgram(prog);

	glGetProgramiv(prog, GL_LINK_STATUS, &status);
	if (status == 0) {
		return 0;
	}

	// detatch
	glDetachShader(prog, fs);
	glDeleteShader(fs);
	glDetachShader(prog, vs);
	glDeleteShader(vs);

	return prog;
}

int ShaderNew::CompileShader(const char * source, int type)
{
	GLint status;

	GLuint shader = glCreateShader(type);
	glShaderSource(shader, 1, &source, NULL);
	glCompileShader(shader);

	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

	if (status == GL_FALSE) {
		char buf[1024];
		GLint len;
		glGetShaderInfoLog(shader, 1024, &len, buf);

		printf("compile failed:%s\n"
			"source:\n %s\n",
			buf, source);
		glDeleteShader(shader);
		return 0;
	}

	return shader;
}

void ShaderNew::InitBuffers()
{
	glGenBuffers(1, &IndexBuffer);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);

	size_t size = MAX_COMMBINE * 6 * sizeof(GLushort);
	GLushort* idxs = new GLushort[size];
	int i;
	for (i=0;i<MAX_COMMBINE;i++)
	{
		idxs[i*6] = i*4;
		idxs[i*6+1] = i*4+1;
		idxs[i*6+2] = i*4+2;
		idxs[i*6+3] = i*4;
		idxs[i*6+4] = i*4+2;
		idxs[i*6+5] = i*4+3;
	}
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, idxs, GL_STATIC_DRAW);
	delete[] idxs;

	glGenBuffers(1, &VertexBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
}

void ShaderNew::Commit()
{
	if (m_sprite_count == 0) {
		return;
	}

	if (m_fbo == 1) {
		int zz = 0;
	}

	sprite();

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);

	glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
	glBufferData(GL_ARRAY_BUFFER, m_sprite_count * SPRITE_FLOAT_NUM * sizeof(float), &m_vb[0], GL_DYNAMIC_DRAW);

	glEnableVertexAttribArray(ATTRIB_VERTEX);
	glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(0));

	glEnableVertexAttribArray(ATTRIB_TEXTCOORD);
	glVertexAttribPointer(ATTRIB_TEXTCOORD, 2, GL_FLOAT, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(8));

	glEnableVertexAttribArray(ATTRIB_COLOR);
	glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(16));

	glEnableVertexAttribArray(ATTRIB_ADDITIVE);
	glVertexAttribPointer(ATTRIB_ADDITIVE, 4, GL_UNSIGNED_BYTE, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(20));

	glDrawElements(GL_TRIANGLES, 6 * m_sprite_count, GL_UNSIGNED_SHORT, 0);

 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glDisableVertexAttribArray(ATTRIB_VERTEX);
	glDisableVertexAttribArray(ATTRIB_TEXTCOORD);
	glDisableVertexAttribArray(ATTRIB_COLOR);
	glDisableVertexAttribArray(ATTRIB_ADDITIVE);

	m_sprite_count = 0;
}

void ShaderNew::CopyVertex(const float vb[16])
{
	float* ptr = m_vb + SPRITE_FLOAT_NUM * m_sprite_count;
	memcpy(ptr, vb, 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
	ptr += 1;
	memcpy(ptr, &vb[4], 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
	ptr += 1;
	memcpy(ptr, &vb[8], 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
	ptr += 1;
	memcpy(ptr, &vb[12], 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
}

}<commit_msg>[FIXED] ShaderNew::Commit()中不应该切换shader<commit_after>#include "ShaderNew.h"
#include "DynamicTexture.h"

#include <GL/GLee.h>
#include <stdio.h>

namespace d2d
{

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

static const int ATTRIB_VERTEX    = 0;
static const int ATTRIB_TEXTCOORD = 1;
static const int ATTRIB_COLOR     = 2;
static const int ATTRIB_ADDITIVE  = 3;

ShaderNew* ShaderNew::m_instance = NULL;

ShaderNew* ShaderNew::Instance()
{
	if (!m_instance)
	{
		m_instance = new ShaderNew();
		m_instance->load();
	}
	return m_instance;
}

ShaderNew::ShaderNew()
{
	m_prog_curr = 0;
	m_prog_sprite = 0;
	m_prog_shape = 0;

	VertexBuffer = IndexBuffer = 0;
	m_sprite_count = 0;
	m_vb = NULL;
	m_tex = 0;
	m_fbo = 0;

	m_color = 0xffffffff;
	m_additive = 0;
}

void ShaderNew::SetSpriteColor(const Colorf& multi, const Colorf& add)
{
	// ABGR
	m_color = ((int)(multi.a * 255 + 0.5f) << 24) |
		((int)(multi.b * 255 + 0.5f) << 16) |
		((int)(multi.g * 255 + 0.5f) << 8) |
		((int)(multi.r * 255 + 0.5f));
	m_additive = ((int)(add.a * 255 + 0.5f) << 24) |
		((int)(add.b * 255 + 0.5f) << 16) |
		((int)(add.g * 255 + 0.5f) << 8) |
		((int)(add.r * 255 + 0.5f));
}

void ShaderNew::SetShapeColor(const Colorf& col)
{
	if (m_prog_curr == m_prog_shape) {
		glUniform4fv(m_col_loc, 1, (GLfloat*)(&col.r));
	}
}

void ShaderNew::sprite()
{
	if (m_prog_curr != m_prog_sprite) {
		Commit();

		glEnable(GL_BLEND);

		// todo Դejoy2dõGL_ONE
		//		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glUseProgram(m_prog_sprite);
		m_prog_curr = m_prog_sprite;
	}
}

void ShaderNew::shape()
{
	if (m_prog_curr != m_prog_shape) {
		Commit();

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glUseProgram(m_prog_shape);
		m_prog_curr = m_prog_shape;
	}
}

void ShaderNew::null()
{
	Commit();

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glUseProgram(0);
	m_prog_curr = 0;
}

void ShaderNew::release()
{
	unload();
}

void ShaderNew::reload()
{
	load();
}

void ShaderNew::SetTexture(int tex)
{
	if (m_tex != tex)
	{
		Commit();
		m_tex = (GLuint)tex;
		glBindTexture(GL_TEXTURE_2D, m_tex);
	}
}

void ShaderNew::SetFBO(int fbo)
{
	if (m_fbo != fbo)
	{
		Commit();
		m_fbo = (GLuint)fbo;
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
	}
}

void ShaderNew::Draw(const float vb[16], int texid)
{
	SetTexture(texid);

	CopyVertex(vb);
	if (++m_sprite_count >= MAX_COMMBINE) {
		Commit();
	}
}

void ShaderNew::Flush()
{
	Commit();

	DynamicTexture::Instance()->DebugDraw();
}

void ShaderNew::load()
{
#if 0
	#define FLOAT_PRECISION \
	"#ifdef GL_FRAGMENT_PRECISION_HIGH  \n" \
	"precision highp float;  \n" \
	"#else  \n" \
	"precision lowp float;  \n" \
	"#endif  \n"
#else
	#define FLOAT_PRECISION \
	"precision lowp float;  \n"
#endif

	static const char * sprite_vs =
		FLOAT_PRECISION
		"attribute vec4 position;  \n"
		"attribute vec2 texcoord;  \n"
		"attribute vec4 color;     \n"
		"attribute vec4 additive;  \n"
		"\n"
		"varying vec2 v_texcoord;  \n"
		"varying vec4 v_fragmentColor;  \n"
		"varying vec4 v_fragmentAddi; \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  gl_Position = position; "
 		"  v_fragmentColor = color / 255.0; \n"
 		"  v_fragmentAddi = additive / 255.0; \n"
		"  v_texcoord = texcoord;  \n"
		"}  \n"
		;

	static const char * sprite_fs =
		FLOAT_PRECISION
		"varying vec4 v_fragmentColor; \n"
		"varying vec4 v_fragmentAddi; \n"
		"varying vec2 v_texcoord;  \n"
		"uniform sampler2D texture0;  \n"
		"\n"
		"void main()  \n"
		"{  \n"
  		"  vec4 tmp = texture2D(texture0, v_texcoord);  \n"
  		"  gl_FragColor.xyz = tmp.xyz * v_fragmentColor.xyz;  \n"
  		"  gl_FragColor.w = tmp.w;    \n"
  		"  gl_FragColor *= v_fragmentColor.w;  \n"
  		"  gl_FragColor.xyz += v_fragmentAddi.xyz * tmp.w;  \n"
		"}  \n"
		;

	static const char* font_fs =
		FLOAT_PRECISION
		"varying vec4 v_fragmentColor; \n"
		"varying vec2 v_texcoord;  \n"
		"uniform sampler2D texture0;  \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  float mask = texture2D(texture0, v_texcoord).a;    \n"
		"  vec4 clr;                                          \n"
		"  clr.rgb = vec3(1.0, 0.0, 0.0);                     \n"
		"  if (mask < 0.5)				                      \n"
		"    clr.a = 0.0;                                     \n"
		"  else                                               \n"
		"    clr.a = 1.0;                                     \n"
		"  gl_FragColor = clr;                                \n"
		"}  \n"
		;

	static const char * shape_vs =
		FLOAT_PRECISION
		"uniform vec4 color;     \n"
		"\n"
		"varying vec4 v_fragmentColor;  \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; "
		"  v_fragmentColor = color; \n"
		"}  \n"
		;

	static const char * shape_fs =
		FLOAT_PRECISION
		"varying vec4 v_fragmentColor; \n"
		"\n"
		"void main()  \n"
		"{  \n"
		"  gl_FragColor = v_fragmentColor;"
		"}  \n"
		;

	glEnable(GL_BLEND);
	// todo Դejoy2dõGL_ONE
	//glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	m_prog_sprite = InitShader(sprite_fs, sprite_vs);
	m_prog_shape = InitShader(shape_fs, shape_vs);
	m_prog_font = InitShader(font_fs, sprite_vs);

	InitBuffers();

	// bind attr
	m_col_loc = glGetUniformLocation(m_prog_shape, "color");

	m_vb = new float[SPRITE_FLOAT_NUM * MAX_COMMBINE];
}

void ShaderNew::unload()
{
// 	delete m_instance;
// 	m_instance = NULL;

	// todo others
	glDeleteBuffers(1, &VertexBuffer);
	glDeleteBuffers(1, &IndexBuffer);

	delete[] m_vb;
	m_vb = NULL;
}

int ShaderNew::InitShader(const char *FS, const char *VS)
{
	GLuint prog = glCreateProgram();

	GLuint fs = CompileShader(FS, GL_FRAGMENT_SHADER);
	if (fs == 0) {
		return 0;
	} else {
		glAttachShader(prog, fs);
	}

	GLuint vs = CompileShader(VS, GL_VERTEX_SHADER);
	if (vs == 0) {
		return 0;
	} else {
		glAttachShader(prog, vs);
	}

 	// attr location
 	glBindAttribLocation(prog, ATTRIB_VERTEX, "position");
 	glBindAttribLocation(prog, ATTRIB_TEXTCOORD, "texcoord");
 	glBindAttribLocation(prog, ATTRIB_COLOR, "color");
 	glBindAttribLocation(prog, ATTRIB_ADDITIVE, "additive");

	// link
	GLint status;
	glLinkProgram(prog);

	glGetProgramiv(prog, GL_LINK_STATUS, &status);
	if (status == 0) {
		return 0;
	}

	// detatch
	glDetachShader(prog, fs);
	glDeleteShader(fs);
	glDetachShader(prog, vs);
	glDeleteShader(vs);

	return prog;
}

int ShaderNew::CompileShader(const char * source, int type)
{
	GLint status;

	GLuint shader = glCreateShader(type);
	glShaderSource(shader, 1, &source, NULL);
	glCompileShader(shader);

	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

	if (status == GL_FALSE) {
		char buf[1024];
		GLint len;
		glGetShaderInfoLog(shader, 1024, &len, buf);

		printf("compile failed:%s\n"
			"source:\n %s\n",
			buf, source);
		glDeleteShader(shader);
		return 0;
	}

	return shader;
}

void ShaderNew::InitBuffers()
{
	glGenBuffers(1, &IndexBuffer);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);

	size_t size = MAX_COMMBINE * 6 * sizeof(GLushort);
	GLushort* idxs = new GLushort[size];
	int i;
	for (i=0;i<MAX_COMMBINE;i++)
	{
		idxs[i*6] = i*4;
		idxs[i*6+1] = i*4+1;
		idxs[i*6+2] = i*4+2;
		idxs[i*6+3] = i*4;
		idxs[i*6+4] = i*4+2;
		idxs[i*6+5] = i*4+3;
	}
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, idxs, GL_STATIC_DRAW);
	delete[] idxs;

	glGenBuffers(1, &VertexBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
}

void ShaderNew::Commit()
{
	if (m_sprite_count == 0) {
		return;
	}

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);

	glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
	glBufferData(GL_ARRAY_BUFFER, m_sprite_count * SPRITE_FLOAT_NUM * sizeof(float), &m_vb[0], GL_DYNAMIC_DRAW);

	glEnableVertexAttribArray(ATTRIB_VERTEX);
	glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(0));

	glEnableVertexAttribArray(ATTRIB_TEXTCOORD);
	glVertexAttribPointer(ATTRIB_TEXTCOORD, 2, GL_FLOAT, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(8));

	glEnableVertexAttribArray(ATTRIB_COLOR);
	glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(16));

	glEnableVertexAttribArray(ATTRIB_ADDITIVE);
	glVertexAttribPointer(ATTRIB_ADDITIVE, 4, GL_UNSIGNED_BYTE, GL_FALSE, SPRITE_FLOAT_NUM, BUFFER_OFFSET(20));

	glDrawElements(GL_TRIANGLES, 6 * m_sprite_count, GL_UNSIGNED_SHORT, 0);

 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glDisableVertexAttribArray(ATTRIB_VERTEX);
	glDisableVertexAttribArray(ATTRIB_TEXTCOORD);
	glDisableVertexAttribArray(ATTRIB_COLOR);
	glDisableVertexAttribArray(ATTRIB_ADDITIVE);

	m_sprite_count = 0;
}

void ShaderNew::CopyVertex(const float vb[16])
{
	float* ptr = m_vb + SPRITE_FLOAT_NUM * m_sprite_count;
	memcpy(ptr, vb, 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
	ptr += 1;
	memcpy(ptr, &vb[4], 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
	ptr += 1;
	memcpy(ptr, &vb[8], 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
	ptr += 1;
	memcpy(ptr, &vb[12], 4 * sizeof(float));
	ptr += 4;
	memcpy(ptr, &m_color, sizeof(int));
	ptr += 1;
	memcpy(ptr, &m_additive, sizeof(int));
}

}<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2011 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <thrust/detail/reference_base.h>
#include <thrust/detail/type_traits.h>
#include <thrust/detail/backend/generic/select_system.h>
#include <thrust/detail/backend/generic/memory.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/swap.h>
#include <iostream>

#include <thrust/system/cpp/detail/tag.h>

namespace thrust
{
namespace detail
{

template<typename Element, typename Pointer, typename Derived>
  template<typename OtherElement, typename OtherPointer, typename OtherDerived>
    reference_base<Element,Pointer,Derived>
      ::reference_base(const reference_base<OtherElement,OtherPointer,OtherDerived> &other,
                       typename thrust::detail::enable_if_convertible<
                         typename reference_base<OtherElement,OtherPointer,OtherDerived>::pointer,
                         pointer
                       >::type *)
        : m_ptr(other.m_ptr)
{}

template<typename Element, typename Pointer, typename Derived>
  reference_base<Element,Pointer,Derived>
    ::reference_base(const pointer &ptr)
      : m_ptr(ptr)
{}

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::pointer
    reference_base<Element,Pointer,Derived>
      ::operator&() const
{
  return m_ptr;
} // end reference_base::operator&()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator=(const value_type &v)
{
  assign_from(&v);
  return static_cast<derived_type&>(*this);
} // end reference_base::operator=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator=(const reference_base &other)
{
  assign_from(&other);
  return static_cast<derived_type&>(*this);
} // end reference_base::operator=()

template<typename Element, typename Pointer, typename Derived>
  template<typename OtherElement, typename OtherPointer, typename OtherDerived>
    typename reference_base<Element,Pointer,Derived>::derived_type &
      reference_base<Element,Pointer,Derived>
        ::operator=(const reference_base<OtherElement,OtherPointer,OtherDerived> &other)
{
  assign_from(&other);
  return static_cast<derived_type&>(*this);
} // end reference_base::operator=()

template<typename Element, typename Pointer, typename Derived>
  reference_base<Element,Pointer,Derived>
    ::operator typename reference_base<Element,Pointer,Derived>::value_type () const
{
  using thrust::detail::backend::generic::select_system;
  using thrust::detail::backend::generic::get_value;

  typedef typename thrust::iterator_space<pointer>::type space;

  return get_value(select_system(space()), m_ptr);
} // end reference_base::operator value_type ()

template<typename Element, typename Pointer, typename Derived>
  template<typename OtherPointer>
    void reference_base<Element,Pointer,Derived>
      ::assign_from(OtherPointer src)
{
  using thrust::detail::backend::generic::select_system;
  using thrust::detail::backend::generic::assign_value;

  typedef typename thrust::iterator_space<pointer>::type      space1;
  typedef typename thrust::iterator_space<OtherPointer>::type space2;

  assign_value(select_system(space1(), space2()), m_ptr, src);
} // end assign_from()

template<typename Element, typename Pointer, typename Derived>
  void reference_base<Element,Pointer,Derived>
    ::swap(derived_type &other)
{
  using thrust::detail::backend::generic::select_system;
  using thrust::detail::backend::generic::iter_swap;

  typedef typename thrust::iterator_space<pointer>::type space;

  iter_swap(select_system(space(), space()), m_ptr, other.m_ptr);
} // end reference_base::swap()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator++(void)
{
  value_type temp = *this;
  ++temp;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator++()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::value_type
    reference_base<Element,Pointer,Derived>
      ::operator++(int)
{
  value_type temp = *this;
  value_type result = temp++;
  *this = temp;
  return result;
} // end reference_base::operator++()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator+=(const value_type &rhs)
{
  value_type temp = *this;
  temp += rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator+=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator--(void)
{
  value_type temp = *this;
  --temp;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator--()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::value_type
    reference_base<Element,Pointer,Derived>
      ::operator--(int)
{
  value_type temp = *this;
  value_type result = temp--;
  *this = temp;
  return result;
} // end reference_base::operator--()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator-=(const value_type &rhs)
{
  value_type temp = *this;
  temp -= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator-=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator*=(const value_type &rhs)
{
  value_type temp = *this;
  temp *= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator*=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator/=(const value_type &rhs)
{
  value_type temp = *this;
  temp /= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator/=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator%=(const value_type &rhs)
{
  value_type temp = *this;
  temp %= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator%=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator<<=(const value_type &rhs)
{
  value_type temp = *this;
  temp <<= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator<<=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator>>=(const value_type &rhs)
{
  value_type temp = *this;
  temp >>= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator>>=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator&=(const value_type &rhs)
{
  value_type temp = *this;
  temp &= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator&=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator|=(const value_type &rhs)
{
  value_type temp = *this;
  temp |= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator|=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator^=(const value_type &rhs)
{
  value_type temp = *this;
  temp ^= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator^=()

} // end detail
} // end thrust

<commit_msg>Provide a specialization for is_convertible<reference_base<Element,Pointer,Derived>, Element><commit_after>/*
 *  Copyright 2008-2011 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <thrust/detail/reference_base.h>
#include <thrust/detail/type_traits.h>
#include <thrust/detail/backend/generic/select_system.h>
#include <thrust/detail/backend/generic/memory.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/swap.h>
#include <iostream>

#include <thrust/system/cpp/detail/tag.h>

namespace thrust
{
namespace detail
{

template<typename Element, typename Pointer, typename Derived>
  template<typename OtherElement, typename OtherPointer, typename OtherDerived>
    reference_base<Element,Pointer,Derived>
      ::reference_base(const reference_base<OtherElement,OtherPointer,OtherDerived> &other,
                       typename thrust::detail::enable_if_convertible<
                         typename reference_base<OtherElement,OtherPointer,OtherDerived>::pointer,
                         pointer
                       >::type *)
        : m_ptr(other.m_ptr)
{}

template<typename Element, typename Pointer, typename Derived>
  reference_base<Element,Pointer,Derived>
    ::reference_base(const pointer &ptr)
      : m_ptr(ptr)
{}

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::pointer
    reference_base<Element,Pointer,Derived>
      ::operator&() const
{
  return m_ptr;
} // end reference_base::operator&()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator=(const value_type &v)
{
  assign_from(&v);
  return static_cast<derived_type&>(*this);
} // end reference_base::operator=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator=(const reference_base &other)
{
  assign_from(&other);
  return static_cast<derived_type&>(*this);
} // end reference_base::operator=()

template<typename Element, typename Pointer, typename Derived>
  template<typename OtherElement, typename OtherPointer, typename OtherDerived>
    typename reference_base<Element,Pointer,Derived>::derived_type &
      reference_base<Element,Pointer,Derived>
        ::operator=(const reference_base<OtherElement,OtherPointer,OtherDerived> &other)
{
  assign_from(&other);
  return static_cast<derived_type&>(*this);
} // end reference_base::operator=()

template<typename Element, typename Pointer, typename Derived>
  reference_base<Element,Pointer,Derived>
    ::operator typename reference_base<Element,Pointer,Derived>::value_type () const
{
  using thrust::detail::backend::generic::select_system;
  using thrust::detail::backend::generic::get_value;

  typedef typename thrust::iterator_space<pointer>::type space;

  return get_value(select_system(space()), m_ptr);
} // end reference_base::operator value_type ()

template<typename Element, typename Pointer, typename Derived>
  template<typename OtherPointer>
    void reference_base<Element,Pointer,Derived>
      ::assign_from(OtherPointer src)
{
  using thrust::detail::backend::generic::select_system;
  using thrust::detail::backend::generic::assign_value;

  typedef typename thrust::iterator_space<pointer>::type      space1;
  typedef typename thrust::iterator_space<OtherPointer>::type space2;

  assign_value(select_system(space1(), space2()), m_ptr, src);
} // end assign_from()

template<typename Element, typename Pointer, typename Derived>
  void reference_base<Element,Pointer,Derived>
    ::swap(derived_type &other)
{
  using thrust::detail::backend::generic::select_system;
  using thrust::detail::backend::generic::iter_swap;

  typedef typename thrust::iterator_space<pointer>::type space;

  iter_swap(select_system(space(), space()), m_ptr, other.m_ptr);
} // end reference_base::swap()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator++(void)
{
  value_type temp = *this;
  ++temp;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator++()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::value_type
    reference_base<Element,Pointer,Derived>
      ::operator++(int)
{
  value_type temp = *this;
  value_type result = temp++;
  *this = temp;
  return result;
} // end reference_base::operator++()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator+=(const value_type &rhs)
{
  value_type temp = *this;
  temp += rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator+=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator--(void)
{
  value_type temp = *this;
  --temp;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator--()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::value_type
    reference_base<Element,Pointer,Derived>
      ::operator--(int)
{
  value_type temp = *this;
  value_type result = temp--;
  *this = temp;
  return result;
} // end reference_base::operator--()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator-=(const value_type &rhs)
{
  value_type temp = *this;
  temp -= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator-=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator*=(const value_type &rhs)
{
  value_type temp = *this;
  temp *= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator*=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator/=(const value_type &rhs)
{
  value_type temp = *this;
  temp /= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator/=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator%=(const value_type &rhs)
{
  value_type temp = *this;
  temp %= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator%=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator<<=(const value_type &rhs)
{
  value_type temp = *this;
  temp <<= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator<<=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator>>=(const value_type &rhs)
{
  value_type temp = *this;
  temp >>= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator>>=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator&=(const value_type &rhs)
{
  value_type temp = *this;
  temp &= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator&=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator|=(const value_type &rhs)
{
  value_type temp = *this;
  temp |= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator|=()

template<typename Element, typename Pointer, typename Derived>
  typename reference_base<Element,Pointer,Derived>::derived_type &
    reference_base<Element,Pointer,Derived>
      ::operator^=(const value_type &rhs)
{
  value_type temp = *this;
  temp ^= rhs;
  *this = temp;
  return static_cast<derived_type&>(*this);
} // end reference_base::operator^=()

// XXX iterator_facade tries to instantiate the Reference
//     type when computing the answer to is_convertible<Reference,Value>
//     we can't do that at that point because reference
//     is not complete
//     WAR the problem by specializing is_convertible
template<typename Element, typename Pointer, typename Derived>
  struct is_convertible<reference_base<Element,Pointer,Derived>, Element>
    : thrust::detail::true_type
{};

} // end detail
} // end thrust

<|endoftext|>


<commit_before>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/value_codec.h>
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/tensor/default_value_builder_factory.h>
#include <vespa/eval/tensor/mixed/packed_mixed_tensor.h>
#include <vespa/eval/tensor/sparse/sparse_tensor_value.h>
#include <vespa/eval/tensor/dense/dense_tensor.h>
#include <vespa/vespalib/gtest/gtest.h>

using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::tensor;
using namespace vespalib::eval::packed_mixed_tensor;

Value::UP v_of(const TensorSpec &spec) {
    return value_from_spec(spec, DefaultValueBuilderFactory::get());
}

TEST(MakeInputTest, print_some_test_input) {
    auto dbl = v_of(TensorSpec("double").add({}, 3.0));
    auto trivial = v_of(TensorSpec("tensor(x[1])").add({{"x",0}}, 7.0));
    auto dense = v_of(TensorSpec("tensor<float>(x[2],y[3])").add({{"x",1},{"y",2}}, 17.0));
    auto sparse = v_of(TensorSpec("tensor(x{},y{})").add({{"x","foo"},{"y","bar"}}, 31.0));
    auto mixed = v_of(TensorSpec("tensor<float>(x[2],y{})").add({{"x",1},{"y","quux"}}, 42.0));

    EXPECT_TRUE(dynamic_cast<DoubleValue *>(dbl.get()));
    EXPECT_TRUE(dynamic_cast<DenseTensorView *>(trivial.get()));
    EXPECT_TRUE(dynamic_cast<DenseTensorView *>(dense.get()));
    EXPECT_TRUE(dynamic_cast<SparseTensorValue<double> *>(sparse.get()));
    EXPECT_TRUE(dynamic_cast<PackedMixedTensor *>(mixed.get()));

    EXPECT_EQ(dbl->as_double(), 3.0);
    EXPECT_EQ(trivial->cells().typify<double>()[0], 7.0);
    EXPECT_EQ(dense->cells().typify<float>()[5], 17.0);
    EXPECT_EQ(sparse->cells().typify<double>()[0], 31.0);
    EXPECT_EQ(mixed->cells().typify<float>()[1], 42.0);

    stringref y_look = "bar";
    stringref x_res = "xxx";
    auto view = sparse->index().create_view({1});
    view->lookup({&y_look});
    size_t ss = 12345;
    bool br = view->next_result({&x_res}, ss);
    EXPECT_TRUE(br);
    EXPECT_EQ(ss, 0);
    EXPECT_EQ(x_res, "foo");
    br = view->next_result({&x_res}, ss);
    EXPECT_FALSE(br);

    ss = 12345;
    view = mixed->index().create_view({});
    view->lookup({});
    br = view->next_result({&x_res}, ss);
    EXPECT_TRUE(br);
    EXPECT_EQ(ss, 0);
    EXPECT_EQ(x_res, "quux");
}

GTEST_MAIN_RUN_ALL_TESTS()
<commit_msg>fix naming in test<commit_after>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/value_codec.h>
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/tensor/default_value_builder_factory.h>
#include <vespa/eval/tensor/mixed/packed_mixed_tensor.h>
#include <vespa/eval/tensor/sparse/sparse_tensor_value.h>
#include <vespa/eval/tensor/dense/dense_tensor.h>
#include <vespa/vespalib/gtest/gtest.h>

using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::tensor;
using namespace vespalib::eval::packed_mixed_tensor;

Value::UP v_of(const TensorSpec &spec) {
    return value_from_spec(spec, DefaultValueBuilderFactory::get());
}

TEST(DefaultValueBuilderFactoryTest, all_built_value_types_are_correct) {
    auto dbl = v_of(TensorSpec("double").add({}, 3.0));
    auto trivial = v_of(TensorSpec("tensor(x[1])").add({{"x",0}}, 7.0));
    auto dense = v_of(TensorSpec("tensor<float>(x[2],y[3])").add({{"x",1},{"y",2}}, 17.0));
    auto sparse = v_of(TensorSpec("tensor(x{},y{})").add({{"x","foo"},{"y","bar"}}, 31.0));
    auto mixed = v_of(TensorSpec("tensor<float>(x[2],y{})").add({{"x",1},{"y","quux"}}, 42.0));

    EXPECT_TRUE(dynamic_cast<DoubleValue *>(dbl.get()));
    EXPECT_TRUE(dynamic_cast<DenseTensorView *>(trivial.get()));
    EXPECT_TRUE(dynamic_cast<DenseTensorView *>(dense.get()));
    EXPECT_TRUE(dynamic_cast<SparseTensorValue<double> *>(sparse.get()));
    EXPECT_TRUE(dynamic_cast<PackedMixedTensor *>(mixed.get()));

    EXPECT_EQ(dbl->as_double(), 3.0);
    EXPECT_EQ(trivial->cells().typify<double>()[0], 7.0);
    EXPECT_EQ(dense->cells().typify<float>()[5], 17.0);
    EXPECT_EQ(sparse->cells().typify<double>()[0], 31.0);
    EXPECT_EQ(mixed->cells().typify<float>()[1], 42.0);

    stringref y_look = "bar";
    stringref x_res = "xxx";
    auto view = sparse->index().create_view({1});
    view->lookup({&y_look});
    size_t ss = 12345;
    bool br = view->next_result({&x_res}, ss);
    EXPECT_TRUE(br);
    EXPECT_EQ(ss, 0);
    EXPECT_EQ(x_res, "foo");
    br = view->next_result({&x_res}, ss);
    EXPECT_FALSE(br);

    ss = 12345;
    view = mixed->index().create_view({});
    view->lookup({});
    br = view->next_result({&x_res}, ss);
    EXPECT_TRUE(br);
    EXPECT_EQ(ss, 0);
    EXPECT_EQ(x_res, "quux");
}

GTEST_MAIN_RUN_ALL_TESTS()
<|endoftext|>


<commit_before>// Ignore unused parameter warnings coming from cppuint headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/serial_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/edge_edge2.h>
#include <libmesh/face_quad4.h>
#include <libmesh/dof_map.h>
#include <libmesh/linear_implicit_system.h>
#include <libmesh/mesh_refinement.h>

#include "test_comm.h"

using namespace libMesh;

class MixedDimensionMeshTest : public CppUnit::TestCase {
  /**
   * The goal of this test is to ensure that a 2D mesh with 1D elements overlapping
   * on the edge is consistent. That is, they share the same global node numbers and
   * the same dof numbers for a variable.
   */
public:
  CPPUNIT_TEST_SUITE( MixedDimensionMeshTest );

  CPPUNIT_TEST( testMesh );
  CPPUNIT_TEST( testDofOrdering );
  CPPUNIT_TEST( testPointLocatorList );
  CPPUNIT_TEST( testPointLocatorTree );

  CPPUNIT_TEST_SUITE_END();

protected:

  SerialMesh* _mesh;

  void build_mesh()
  {
    _mesh = new SerialMesh(*TestCommWorld);

    /*
      (0,1)           (1,1)
        x---------------x
        |               |
        |               |
        |               |
        |               |
        |               |
        x---------------x
       (0,0)           (1,0)
        |               |
        |               |
        |               |
        |               |
        x---------------x
       (0,-1)          (1,-1)
     */

    _mesh->set_mesh_dimension(2);

    _mesh->add_point( Point(0.0,-1.0), 4 );
    _mesh->add_point( Point(1.0,-1.0), 5 );
    _mesh->add_point( Point(1.0, 0.0), 1 );
    _mesh->add_point( Point(1.0, 1.0), 2 );
    _mesh->add_point( Point(0.0, 1.0), 3 );
    _mesh->add_point( Point(0.0, 0.0), 0 );

    {
      Elem* elem_top = _mesh->add_elem( new Quad4 );
      elem_top->set_node(0) = _mesh->node_ptr(0);
      elem_top->set_node(1) = _mesh->node_ptr(1);
      elem_top->set_node(2) = _mesh->node_ptr(2);
      elem_top->set_node(3) = _mesh->node_ptr(3);

      Elem* elem_bottom = _mesh->add_elem( new Quad4 );
      elem_bottom->set_node(0) = _mesh->node_ptr(4);
      elem_bottom->set_node(1) = _mesh->node_ptr(5);
      elem_bottom->set_node(2) = _mesh->node_ptr(1);
      elem_bottom->set_node(3) = _mesh->node_ptr(0);

      Elem* edge = _mesh->add_elem( new Edge2 );
      edge->set_node(0) = _mesh->node_ptr(0);
      edge->set_node(1) = _mesh->node_ptr(1);
    }

    // libMesh will renumber, but we numbered according to its scheme
    // anyway. We do this because when we call uniformly_refine subsequenly,
    // it's going use skip_renumber=false.
    _mesh->prepare_for_use(false /*skip_renumber*/);
  }

public:
  void setUp()
  {
    this->build_mesh();
  }

  void tearDown()
  {
    delete _mesh;
   }

  void testMesh()
  {
    // There'd better be 3 elements
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)3, _mesh->n_elem() );

    // There'd better be only 6 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)6, _mesh->n_nodes() );

    /* The nodes for the EDGE2 element should have the same global ids
       as the bottom edge of the top QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(0)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(0)->node(1) );

    /* The nodes for the EDGE2 element should have the same global ids
       as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(1)->node(2) );

    /* The nodes for the bottom edge of the top QUAD4 element should have
       the same global ids as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(1), _mesh->elem(1)->node(2) );
  }

  void testDofOrdering()
  {
    EquationSystems es(*_mesh);
    es.add_system<LinearImplicitSystem>("TestDofSystem");
    es.get_system("TestDofSystem").add_variable("u",FIRST);
    es.init();

    DofMap& dof_map = es.get_system("TestDofSystem").get_dof_map();

    std::vector<dof_id_type> top_quad_dof_indices, bottom_quad_dof_indices, edge_dof_indices;

    dof_map.dof_indices( _mesh->elem(0), top_quad_dof_indices );
    dof_map.dof_indices( _mesh->elem(1), bottom_quad_dof_indices );
    dof_map.dof_indices( _mesh->elem(2), edge_dof_indices );

    /* The dofs for the EDGE2 element should be the same
       as the bottom edge of the top QUAD4 dofs */
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[0], top_quad_dof_indices[0] );
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[1], top_quad_dof_indices[1] );

    /* The dofs for the EDGE2 element should be the same
       as the top edge of the bottom QUAD4 dofs */
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[0], bottom_quad_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[1], bottom_quad_dof_indices[2] );

    /* The nodes for the bottom edge of the top QUAD4 element should have
       the same global ids as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( top_quad_dof_indices[0], bottom_quad_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( top_quad_dof_indices[1], bottom_quad_dof_indices[2] );
  }

  void testPointLocatorList()
  {
    AutoPtr<PointLocatorBase> locator = PointLocatorBase::build(LIST,*_mesh);

    Point top_point(0.4, 0.5);
    const Elem* top_elem = (*locator)(top_point);
    CPPUNIT_ASSERT(top_elem);

    // We should have gotten back the top quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)0, top_elem->id() );

    Point bottom_point(0.5, -0.5);
    const Elem* bottom_elem = (*locator)(bottom_point);
    CPPUNIT_ASSERT(bottom_elem);

    // We should have gotten back the bottom quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)1, bottom_elem->id() );
  }

  void testPointLocatorTree()
  {
    AutoPtr<PointLocatorBase> locator = _mesh->sub_point_locator();

    Point top_point(0.5, 0.5);
    const Elem* top_elem = (*locator)(top_point);
    CPPUNIT_ASSERT(top_elem);

    // We should have gotten back the top quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)0, top_elem->id() );

    Point bottom_point(0.5, -0.5);
    const Elem* bottom_elem = (*locator)(bottom_point);
    CPPUNIT_ASSERT(bottom_elem);

    // We should have gotten back the bottom quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)1, bottom_elem->id() );
  }

};

class MixedDimensionRefinedMeshTest : public MixedDimensionMeshTest {
  /**
   * The goal of this test is the same as the previous, but now we do a
   * uniform refinement and make sure the result mesh is consistent. i.e.
   * the new node shared between the 1D elements is the same as the node
   * shared on the underlying quads, and so on.
   */
public:
  CPPUNIT_TEST_SUITE( MixedDimensionRefinedMeshTest );

  CPPUNIT_TEST( testMesh );
  CPPUNIT_TEST( testDofOrdering );

  CPPUNIT_TEST_SUITE_END();

  // Yes, this is necesarry. Somewhere in those macros is a protected/private
public:

  void setUp()
  {
    /*

        3-------10------2
        |       |       |
        |   5   |   6   |
        8-------7-------9
        |       |       |
        |   3   |   4   |
        0-------6-------1
        |       |       |
        |   9   |  10   |
       13------12-------14
        |       |       |
        |   7   |   8   |
        4-------11------5

     */
    this->build_mesh();
#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement(*_mesh).uniformly_refine(1);
#endif
  }

  void testMesh()
  {
#ifdef LIBMESH_ENABLE_AMR
    // We should have 13 total and 10 active elements.
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)13, _mesh->n_elem() );
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)10, _mesh->n_active_elem() );

    // We should have 15 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)15, _mesh->n_nodes() );

    // EDGE2,id=11 should have same nodes of bottom of QUAD4, id=3
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(0), _mesh->elem(3)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(1), _mesh->elem(3)->node(1) );

    // EDGE2,id=12 should have same nodes of bottom of QUAD4, id=4
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(0), _mesh->elem(4)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(1), _mesh->elem(4)->node(1) );

    // EDGE2,id=11 should have same nodes of top of QUAD4, id=9
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(0), _mesh->elem(9)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(1), _mesh->elem(9)->node(2) );

    // EDGE2,id=12 should have same nodes of top of QUAD4, id=10
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(0), _mesh->elem(10)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(1), _mesh->elem(10)->node(2) );

    // Shared node between the EDGE2 elements should have the same global id
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(1), _mesh->elem(12)->node(0) );
#endif
  }

  void testDofOrdering()
  {
#ifdef LIBMESH_ENABLE_AMR
    EquationSystems es(*_mesh);
    es.add_system<LinearImplicitSystem>("TestDofSystem");
    es.get_system("TestDofSystem").add_variable("u",FIRST);
    es.init();

    DofMap& dof_map = es.get_system("TestDofSystem").get_dof_map();

    std::vector<dof_id_type> top_quad3_dof_indices, top_quad4_dof_indices;
    std::vector<dof_id_type> bottom_quad9_dof_indices, bottom_quad10_dof_indices;
    std::vector<dof_id_type> edge11_dof_indices, edge12_dof_indices;

    dof_map.dof_indices( _mesh->elem(3), top_quad3_dof_indices );
    dof_map.dof_indices( _mesh->elem(4), top_quad4_dof_indices );
    dof_map.dof_indices( _mesh->elem(9), bottom_quad9_dof_indices );
    dof_map.dof_indices( _mesh->elem(10), bottom_quad10_dof_indices );
    dof_map.dof_indices( _mesh->elem(11), edge11_dof_indices );
    dof_map.dof_indices( _mesh->elem(12), edge12_dof_indices );

    // EDGE2,id=11 should have same dofs as of bottom of QUAD4, id=3
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[0], top_quad3_dof_indices[0] );
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[1], top_quad3_dof_indices[1] );

    // EDGE2,id=12 should have same dofs of bottom of QUAD4, id=4
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[0], top_quad4_dof_indices[0] );
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[1], top_quad4_dof_indices[1] );

    // EDGE2,id=11 should have same dofs of top of QUAD4, id=9
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[0], bottom_quad9_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[1], bottom_quad9_dof_indices[2] );

    // EDGE2,id=12 should have same dofs of top of QUAD4, id=10
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[0], bottom_quad10_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[1], bottom_quad10_dof_indices[2] );

    //EDGE2 elements should have same shared dof number
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[1], edge12_dof_indices[0] );
#endif
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION( MixedDimensionMeshTest );
CPPUNIT_TEST_SUITE_REGISTRATION( MixedDimensionRefinedMeshTest );
<commit_msg>Actually test mixed dimension cases<commit_after>// Ignore unused parameter warnings coming from cppuint headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/serial_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/edge_edge2.h>
#include <libmesh/face_quad4.h>
#include <libmesh/dof_map.h>
#include <libmesh/linear_implicit_system.h>
#include <libmesh/mesh_refinement.h>

#include "test_comm.h"

using namespace libMesh;

class MixedDimensionMeshTest : public CppUnit::TestCase {
  /**
   * The goal of this test is to ensure that a 2D mesh with 1D elements overlapping
   * on the edge is consistent. That is, they share the same global node numbers and
   * the same dof numbers for a variable.
   */
public:
  CPPUNIT_TEST_SUITE( MixedDimensionMeshTest );

  CPPUNIT_TEST( testMesh );
  CPPUNIT_TEST( testDofOrdering );
  CPPUNIT_TEST( testPointLocatorList );
  CPPUNIT_TEST( testPointLocatorTree );

  CPPUNIT_TEST_SUITE_END();

protected:

  SerialMesh* _mesh;

  void build_mesh()
  {
    _mesh = new SerialMesh(*TestCommWorld);

    /*
      (0,1)           (1,1)
        x---------------x
        |               |
        |               |
        |               |
        |               |
        |               |
        x---------------x
       (0,0)           (1,0)
        |               |
        |               |
        |               |
        |               |
        x---------------x
       (0,-1)          (1,-1)
     */

    _mesh->set_mesh_dimension(2);

    _mesh->add_point( Point(0.0,-1.0), 4 );
    _mesh->add_point( Point(1.0,-1.0), 5 );
    _mesh->add_point( Point(1.0, 0.0), 1 );
    _mesh->add_point( Point(1.0, 1.0), 2 );
    _mesh->add_point( Point(0.0, 1.0), 3 );
    _mesh->add_point( Point(0.0, 0.0), 0 );

    {
      Elem* elem_top = _mesh->add_elem( new Quad4 );
      elem_top->set_node(0) = _mesh->node_ptr(0);
      elem_top->set_node(1) = _mesh->node_ptr(1);
      elem_top->set_node(2) = _mesh->node_ptr(2);
      elem_top->set_node(3) = _mesh->node_ptr(3);

      Elem* elem_bottom = _mesh->add_elem( new Quad4 );
      elem_bottom->set_node(0) = _mesh->node_ptr(4);
      elem_bottom->set_node(1) = _mesh->node_ptr(5);
      elem_bottom->set_node(2) = _mesh->node_ptr(1);
      elem_bottom->set_node(3) = _mesh->node_ptr(0);

      Elem* edge = _mesh->add_elem( new Edge2 );
      edge->set_node(0) = _mesh->node_ptr(0);
      edge->set_node(1) = _mesh->node_ptr(1);

      // 2D elements will have subdomain id 0, this one will have 1
      edge->subdomain_id() = 1;
    }

    // libMesh will renumber, but we numbered according to its scheme
    // anyway. We do this because when we call uniformly_refine subsequenly,
    // it's going use skip_renumber=false.
    _mesh->prepare_for_use(false /*skip_renumber*/);
  }

public:
  void setUp()
  {
    this->build_mesh();
  }

  void tearDown()
  {
    delete _mesh;
   }

  void testMesh()
  {
    // There'd better be 3 elements
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)3, _mesh->n_elem() );

    // There'd better be only 6 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)6, _mesh->n_nodes() );

    /* The nodes for the EDGE2 element should have the same global ids
       as the bottom edge of the top QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(0)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(0)->node(1) );

    /* The nodes for the EDGE2 element should have the same global ids
       as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(1)->node(2) );

    /* The nodes for the bottom edge of the top QUAD4 element should have
       the same global ids as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(1), _mesh->elem(1)->node(2) );
  }

  void testDofOrdering()
  {
    EquationSystems es(*_mesh);
    es.add_system<LinearImplicitSystem>("TestDofSystem");
    es.get_system("TestDofSystem").add_variable("u",FIRST);
    es.init();

    DofMap& dof_map = es.get_system("TestDofSystem").get_dof_map();

    std::vector<dof_id_type> top_quad_dof_indices, bottom_quad_dof_indices, edge_dof_indices;

    dof_map.dof_indices( _mesh->elem(0), top_quad_dof_indices );
    dof_map.dof_indices( _mesh->elem(1), bottom_quad_dof_indices );
    dof_map.dof_indices( _mesh->elem(2), edge_dof_indices );

    /* The dofs for the EDGE2 element should be the same
       as the bottom edge of the top QUAD4 dofs */
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[0], top_quad_dof_indices[0] );
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[1], top_quad_dof_indices[1] );

    /* The dofs for the EDGE2 element should be the same
       as the top edge of the bottom QUAD4 dofs */
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[0], bottom_quad_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[1], bottom_quad_dof_indices[2] );

    /* The nodes for the bottom edge of the top QUAD4 element should have
       the same global ids as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( top_quad_dof_indices[0], bottom_quad_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( top_quad_dof_indices[1], bottom_quad_dof_indices[2] );
  }

  void testPointLocatorList()
  {
    AutoPtr<PointLocatorBase> locator = PointLocatorBase::build(LIST,*_mesh);

    Point top_point(0.4, 0.5);
    const Elem* top_elem = (*locator)(top_point);
    CPPUNIT_ASSERT(top_elem);

    // We should have gotten back the top quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)0, top_elem->id() );

    Point bottom_point(0.5, -0.5);
    const Elem* bottom_elem = (*locator)(bottom_point);
    CPPUNIT_ASSERT(bottom_elem);

    // We should have gotten back the bottom quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)1, bottom_elem->id() );

    // Test getting back the edge
    {
      std::set<subdomain_id_type> subdomain_id; subdomain_id.insert(1);
      Point interface_point( 0.2, 0.0 );
      const Elem* interface_elem = (*locator)(interface_point, &subdomain_id);
      CPPUNIT_ASSERT(interface_elem);

      // We should have gotten back the overlapping edge element
      CPPUNIT_ASSERT_EQUAL( (dof_id_type)2, interface_elem->id() );
    }
  }

  void testPointLocatorTree()
  {
    AutoPtr<PointLocatorBase> locator = _mesh->sub_point_locator();

    Point top_point(0.5, 0.5);
    const Elem* top_elem = (*locator)(top_point);
    CPPUNIT_ASSERT(top_elem);

    // We should have gotten back the top quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)0, top_elem->id() );

    Point bottom_point(0.5, -0.5);
    const Elem* bottom_elem = (*locator)(bottom_point);
    CPPUNIT_ASSERT(bottom_elem);

    // We should have gotten back the bottom quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)1, bottom_elem->id() );

    // Test getting back the edge
    {
      std::set<subdomain_id_type> subdomain_id; subdomain_id.insert(1);
      Point interface_point( 0.5, 0.0 );
      const Elem* interface_elem = (*locator)(interface_point, &subdomain_id);
      CPPUNIT_ASSERT(interface_elem);

      // We should have gotten back the overlapping edge element
      CPPUNIT_ASSERT_EQUAL( (dof_id_type)2, interface_elem->id() );
    }
  }

};

class MixedDimensionRefinedMeshTest : public MixedDimensionMeshTest {
  /**
   * The goal of this test is the same as the previous, but now we do a
   * uniform refinement and make sure the result mesh is consistent. i.e.
   * the new node shared between the 1D elements is the same as the node
   * shared on the underlying quads, and so on.
   */
public:
  CPPUNIT_TEST_SUITE( MixedDimensionRefinedMeshTest );

  CPPUNIT_TEST( testMesh );
  CPPUNIT_TEST( testDofOrdering );

  CPPUNIT_TEST_SUITE_END();

  // Yes, this is necesarry. Somewhere in those macros is a protected/private
public:

  void setUp()
  {
    /*

        3-------10------2
        |       |       |
        |   5   |   6   |
        8-------7-------9
        |       |       |
        |   3   |   4   |
        0-------6-------1
        |       |       |
        |   9   |  10   |
       13------12-------14
        |       |       |
        |   7   |   8   |
        4-------11------5

     */
    this->build_mesh();
#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement(*_mesh).uniformly_refine(1);
#endif
  }

  void testMesh()
  {
#ifdef LIBMESH_ENABLE_AMR
    // We should have 13 total and 10 active elements.
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)13, _mesh->n_elem() );
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)10, _mesh->n_active_elem() );

    // We should have 15 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)15, _mesh->n_nodes() );

    // EDGE2,id=11 should have same nodes of bottom of QUAD4, id=3
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(0), _mesh->elem(3)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(1), _mesh->elem(3)->node(1) );

    // EDGE2,id=12 should have same nodes of bottom of QUAD4, id=4
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(0), _mesh->elem(4)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(1), _mesh->elem(4)->node(1) );

    // EDGE2,id=11 should have same nodes of top of QUAD4, id=9
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(0), _mesh->elem(9)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(1), _mesh->elem(9)->node(2) );

    // EDGE2,id=12 should have same nodes of top of QUAD4, id=10
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(0), _mesh->elem(10)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(12)->node(1), _mesh->elem(10)->node(2) );

    // Shared node between the EDGE2 elements should have the same global id
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(11)->node(1), _mesh->elem(12)->node(0) );
#endif
  }

  void testDofOrdering()
  {
#ifdef LIBMESH_ENABLE_AMR
    EquationSystems es(*_mesh);
    es.add_system<LinearImplicitSystem>("TestDofSystem");
    es.get_system("TestDofSystem").add_variable("u",FIRST);
    es.init();

    DofMap& dof_map = es.get_system("TestDofSystem").get_dof_map();

    std::vector<dof_id_type> top_quad3_dof_indices, top_quad4_dof_indices;
    std::vector<dof_id_type> bottom_quad9_dof_indices, bottom_quad10_dof_indices;
    std::vector<dof_id_type> edge11_dof_indices, edge12_dof_indices;

    dof_map.dof_indices( _mesh->elem(3), top_quad3_dof_indices );
    dof_map.dof_indices( _mesh->elem(4), top_quad4_dof_indices );
    dof_map.dof_indices( _mesh->elem(9), bottom_quad9_dof_indices );
    dof_map.dof_indices( _mesh->elem(10), bottom_quad10_dof_indices );
    dof_map.dof_indices( _mesh->elem(11), edge11_dof_indices );
    dof_map.dof_indices( _mesh->elem(12), edge12_dof_indices );

    // EDGE2,id=11 should have same dofs as of bottom of QUAD4, id=3
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[0], top_quad3_dof_indices[0] );
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[1], top_quad3_dof_indices[1] );

    // EDGE2,id=12 should have same dofs of bottom of QUAD4, id=4
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[0], top_quad4_dof_indices[0] );
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[1], top_quad4_dof_indices[1] );

    // EDGE2,id=11 should have same dofs of top of QUAD4, id=9
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[0], bottom_quad9_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[1], bottom_quad9_dof_indices[2] );

    // EDGE2,id=12 should have same dofs of top of QUAD4, id=10
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[0], bottom_quad10_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( edge12_dof_indices[1], bottom_quad10_dof_indices[2] );

    //EDGE2 elements should have same shared dof number
    CPPUNIT_ASSERT_EQUAL( edge11_dof_indices[1], edge12_dof_indices[0] );
#endif
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION( MixedDimensionMeshTest );
CPPUNIT_TEST_SUITE_REGISTRATION( MixedDimensionRefinedMeshTest );
<|endoftext|>


<commit_before>#include <Bull/Core/Exception/RuntimeError.hpp>
#include <Bull/Core/FileSystem/File.hpp>
#include <Bull/Core/Log/Log.hpp>

#include <Bull/Render/Shader/Shader.hpp>
#include <Bull/Render/Context/GlFunctions.hpp>

namespace Bull
{
    unsigned int Shader::getMaxVertexAttribs()
    {
        int count;

        ensureContext();

        gl::getIntegerv(GL_MAX_VERTEX_ATTRIBS, &count);

        return static_cast<unsigned int>(count);
    }

    Shader::Shader() :
        m_program(gl::createProgram())
    {
        /// Nothing
    }

    Shader::~Shader()
    {
        if(isValid())
        {
            gl::deleteProgram(m_program);
        }
    }

    bool Shader::create(const ShaderBinary& binary)
    {
        if(binary.isValid())
        {
            gl::programBinary(m_program, binary.format, binary.getBuffer(), binary.getCapacity());
        }

        return false;
    }

    bool Shader::attach(const ShaderStage& stage)
    {
        if(stage.isValid() && stage.isCompiled())
        {
            gl::attachShader(m_program, stage.getSystemHandler());

            return true;
        }

        return false;
    }

    bool Shader::attachFromPath(const Path& path, ShaderStageType::ShaderStageType type)
    {
        ShaderStage stage;
        ShaderStageParameters parameters;

        parameters.type = type;

        return stage.loadFromPath(path, parameters) && attach(stage);
    }

    bool Shader::attachFromStream(InStream& stream, ShaderStageType::ShaderStageType type)
    {
        ShaderStage stage;
        ShaderStageParameters parameters;

        parameters.type = type;

        return stage.loadFromStream(stream, parameters) && attach(stage);
    }

    bool Shader::attachFromMemory(const void* data, Index length, ShaderStageType::ShaderStageType type)
    {
        ShaderStage stage;
        ShaderStageParameters parameters;

        parameters.type = type;

        return stage.loadFromMemory(data, length, parameters) && attach(stage);
    }

    bool Shader::link()
    {
        if(isValid())
        {
            gl::linkProgram(m_program);

            if(!isLinked())
            {
                Log::get()->write(getErrorMessage(), Log::Level::Error);

                return false;
            }
        }

        return true;
    }

    void Shader::bind() const
    {
        if(isValid())
        {
            gl::useProgram(m_program);
        }
    }

    bool Shader::isValid() const
    {
        return gl::isProgram(m_program) == GL_TRUE;
    }

    bool Shader::isLinked() const
    {
        int status = 0;
        gl::getProgramiv(m_program, GL_LINK_STATUS, &status);

        return status == GL_TRUE;
    }

    bool Shader::setUniform(const String& name, int uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform1i)
        {
            gl::programUniform1i(m_program, location, uniform);
        }
        else
        {
            bind();

            gl::uniform1i(location, uniform);
        }

        return true;
    }

    bool  Shader::setUniform(const String& name, unsigned int uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform1i)
        {
            gl::programUniform1i(m_program, location, uniform);
        }
        else
        {
            bind();

            gl::uniform1i(location, uniform);
        }

        return true;
    }

    bool Shader::setUniform(const String& name, float uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform1i)
        {
            gl::programUniform1f(m_program, location, uniform);
        }
        else
        {
            bind();

            gl::uniform1f(location, uniform);
        }

        return true;
    }

    bool Shader::setUniformColor(const String& name, const Color& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform4f)
        {
            gl::programUniform4f(m_program, location,
                                 static_cast<float>(uniform.red)   / 255.f,
                                 static_cast<float>(uniform.green) / 255.f,
                                 static_cast<float>(uniform.blue)  / 255.f,
                                 static_cast<float>(uniform.alpha) / 255.f);
        }
        else
        {
            bind();

            gl::uniform4f(location,
                          static_cast<float>(uniform.red)   / 255.f,
                          static_cast<float>(uniform.green) / 255.f,
                          static_cast<float>(uniform.blue)  / 255.f,
                          static_cast<float>(uniform.alpha) / 255.f);
        }

        return true;
    }

    bool Shader::setUniformVector(const String& name, const Vector<float, 2>& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform2f)
        {
            gl::programUniform2f(m_program, location, uniform.at(0), uniform.at(1));
        }
        else
        {
            bind();

            gl::uniform2f(location, uniform.at(0), uniform.at(1));
        }

        return true;
    }

    bool Shader::setUniformVector(const String& name, const Vector<float, 3>& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform3f)
        {
            gl::programUniform3f(m_program, location, uniform.at(0), uniform.at(1), uniform.at(2));
        }
        else
        {
            bind();

            gl::uniform3f(location, uniform.at(0), uniform.at(1), uniform.at(2));
        }

        return true;
    }

    bool Shader::setUniformVector(const String& name, const Vector<float, 4>& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform4f)
        {
            gl::programUniform4f(m_program, location, uniform.at(0), uniform.at(1), uniform.at(2), uniform.at(3));
        }
        else
        {
            bind();

            gl::uniform4f(location, uniform.at(0), uniform.at(1), uniform.at(2), uniform.at(3));
        }

        return true;
    }

    bool Shader::setUniformMatrix(const String& name, const Matrix4F& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniformMatrix4fv)
        {
            gl::programUniformMatrix4fv(m_program, location, 1, true, uniform.getPtr());
        }
        else
        {
            bind();

            gl::uniformMatrix4fv(location, 1, true, uniform.getPtr());
        }

        return true;
    }

    ShaderBinary Shader::getBinary() const
    {
        ShaderBinary binary;

        if(isValid() && isLinked())
        {
            int length;

            gl::getProgramiv(m_program,  GL_PROGRAM_BINARY_LENGTH, &length);

            if(length)
            {
                binary.create(length);

                gl::getProgramBinary(getSystemHandler(), length, nullptr, &binary.format, &binary[0]);

                if(!binary.isValid())
                {
                    throw RuntimeError("Failed to download program binary");
                }
            }
        }

        return binary;
    }

    unsigned int Shader::getSystemHandler() const
    {
        return m_program;
    }

    String Shader::getErrorMessage() const
    {
        int capacity;
        String message;

        gl::getProgramiv(m_program, GL_INFO_LOG_LENGTH, &capacity);

        if(capacity)
        {
            message.setSize(static_cast<Index>(capacity));
            gl::getProgramInfoLog(m_program, capacity, nullptr, &message[0]);
        }

        return message;
    }

    int Shader::getUniformLocation(const String& name)
    {
        return gl::getUniformLocation(m_program, name.getBuffer());
    }
}
<commit_msg>[Render/Shader] Implement loading from binary<commit_after>#include <Bull/Core/Exception/RuntimeError.hpp>
#include <Bull/Core/FileSystem/File.hpp>
#include <Bull/Core/Log/Log.hpp>

#include <Bull/Render/Shader/Shader.hpp>
#include <Bull/Render/Context/GlFunctions.hpp>

namespace Bull
{
    unsigned int Shader::getMaxVertexAttribs()
    {
        int count;

        ensureContext();

        gl::getIntegerv(GL_MAX_VERTEX_ATTRIBS, &count);

        return static_cast<unsigned int>(count);
    }

    Shader::Shader() :
        m_program(gl::createProgram())
    {
        /// Nothing
    }

    Shader::~Shader()
    {
        if(isValid())
        {
            gl::deleteProgram(m_program);
        }
    }

    bool Shader::create(const ShaderBinary& binary)
    {
        if(binary.isValid())
        {
            gl::programBinary(m_program, binary.format, binary.getBuffer(), binary.getCapacity());
        }

        return false;
    }

    bool Shader::attach(const ShaderStage& stage)
    {
        if(stage.isValid() && stage.isCompiled())
        {
            gl::attachShader(m_program, stage.getSystemHandler());

            return true;
        }

        return false;
    }

    bool Shader::attachFromPath(const Path& path, ShaderStageType::ShaderStageType type)
    {
        ShaderStage stage;
        ShaderStageParameters parameters;

        parameters.type = type;

        return stage.loadFromPath(path, parameters) && attach(stage);
    }

    bool Shader::attachFromStream(InStream& stream, ShaderStageType::ShaderStageType type)
    {
        ShaderStage stage;
        ShaderStageParameters parameters;

        parameters.type = type;

        return stage.loadFromStream(stream, parameters) && attach(stage);
    }

    bool Shader::attachFromMemory(const void* data, Index length, ShaderStageType::ShaderStageType type)
    {
        ShaderStage stage;
        ShaderStageParameters parameters;

        parameters.type = type;

        return stage.loadFromMemory(data, length, parameters) && attach(stage);
    }

    bool Shader::loadFromBinary(const ShaderBinary& binary)
    {
        if(binary.isValid())
        {
            gl::programBinary(m_program, binary.format, binary.getBuffer(), binary.getCapacity());

            return true;
        }

        return false;
    }

    bool Shader::link()
    {
        if(isValid())
        {
            gl::linkProgram(m_program);

            if(!isLinked())
            {
                Log::get()->write(getErrorMessage(), Log::Level::Error);

                return false;
            }
        }

        return true;
    }

    void Shader::bind() const
    {
        if(isValid())
        {
            gl::useProgram(m_program);
        }
    }

    bool Shader::isValid() const
    {
        return gl::isProgram(m_program) == GL_TRUE;
    }

    bool Shader::isLinked() const
    {
        int status = 0;
        gl::getProgramiv(m_program, GL_LINK_STATUS, &status);

        return status == GL_TRUE;
    }

    bool Shader::setUniform(const String& name, int uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform1i)
        {
            gl::programUniform1i(m_program, location, uniform);
        }
        else
        {
            bind();

            gl::uniform1i(location, uniform);
        }

        return true;
    }

    bool  Shader::setUniform(const String& name, unsigned int uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform1i)
        {
            gl::programUniform1i(m_program, location, uniform);
        }
        else
        {
            bind();

            gl::uniform1i(location, uniform);
        }

        return true;
    }

    bool Shader::setUniform(const String& name, float uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform1i)
        {
            gl::programUniform1f(m_program, location, uniform);
        }
        else
        {
            bind();

            gl::uniform1f(location, uniform);
        }

        return true;
    }

    bool Shader::setUniformColor(const String& name, const Color& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform4f)
        {
            gl::programUniform4f(m_program, location,
                                 static_cast<float>(uniform.red)   / 255.f,
                                 static_cast<float>(uniform.green) / 255.f,
                                 static_cast<float>(uniform.blue)  / 255.f,
                                 static_cast<float>(uniform.alpha) / 255.f);
        }
        else
        {
            bind();

            gl::uniform4f(location,
                          static_cast<float>(uniform.red)   / 255.f,
                          static_cast<float>(uniform.green) / 255.f,
                          static_cast<float>(uniform.blue)  / 255.f,
                          static_cast<float>(uniform.alpha) / 255.f);
        }

        return true;
    }

    bool Shader::setUniformVector(const String& name, const Vector<float, 2>& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform2f)
        {
            gl::programUniform2f(m_program, location, uniform.at(0), uniform.at(1));
        }
        else
        {
            bind();

            gl::uniform2f(location, uniform.at(0), uniform.at(1));
        }

        return true;
    }

    bool Shader::setUniformVector(const String& name, const Vector<float, 3>& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform3f)
        {
            gl::programUniform3f(m_program, location, uniform.at(0), uniform.at(1), uniform.at(2));
        }
        else
        {
            bind();

            gl::uniform3f(location, uniform.at(0), uniform.at(1), uniform.at(2));
        }

        return true;
    }

    bool Shader::setUniformVector(const String& name, const Vector<float, 4>& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniform4f)
        {
            gl::programUniform4f(m_program, location, uniform.at(0), uniform.at(1), uniform.at(2), uniform.at(3));
        }
        else
        {
            bind();

            gl::uniform4f(location, uniform.at(0), uniform.at(1), uniform.at(2), uniform.at(3));
        }

        return true;
    }

    bool Shader::setUniformMatrix(const String& name, const Matrix4F& uniform)
    {
        int location = getUniformLocation(name);

        if(location == -1)
        {
            return false;
        }

        if(gl::programUniformMatrix4fv)
        {
            gl::programUniformMatrix4fv(m_program, location, 1, true, uniform.getPtr());
        }
        else
        {
            bind();

            gl::uniformMatrix4fv(location, 1, true, uniform.getPtr());
        }

        return true;
    }

    ShaderBinary Shader::getBinary() const
    {
        ShaderBinary binary;

        if(isValid() && isLinked())
        {
            int length;

            gl::getProgramiv(m_program,  GL_PROGRAM_BINARY_LENGTH, &length);

            if(length)
            {
                binary.create(length);

                gl::getProgramBinary(getSystemHandler(), length, nullptr, &binary.format, &binary[0]);

                if(!binary.isValid())
                {
                    throw RuntimeError("Failed to download program binary");
                }
            }
        }

        return binary;
    }

    unsigned int Shader::getSystemHandler() const
    {
        return m_program;
    }

    String Shader::getErrorMessage() const
    {
        int capacity;
        String message;

        gl::getProgramiv(m_program, GL_INFO_LOG_LENGTH, &capacity);

        if(capacity)
        {
            message.setSize(static_cast<Index>(capacity));
            gl::getProgramInfoLog(m_program, capacity, nullptr, &message[0]);
        }

        return message;
    }

    int Shader::getUniformLocation(const String& name)
    {
        return gl::getUniformLocation(m_program, name.getBuffer());
    }
}
<|endoftext|>