GL1: work around lack of NPOT textures in Windows OpenGL renderer.
OpenGL 1.1 permits implementations to reject non-power-of-2 sized textures. In practice this only affects the default Windows OpenGL implementation, i.e. with no vendor drivers installed. This is still important in case the application runs in a VM.
This commit is contained in:
parent
7787923d05
commit
819c4c5742
@ -201,6 +201,31 @@ Canvas::Fill *OpenGl1Renderer::SelectFill(hFill hcf) {
|
|||||||
return fill;
|
return fill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int RoundUpToPowerOfTwo(int v)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 31; i++) {
|
||||||
|
int vt = (1 << i);
|
||||||
|
if(vt >= v) {
|
||||||
|
return vt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool NeedsGl1V1Workaround()
|
||||||
|
{
|
||||||
|
static bool didGlVersionCheck, needsGl1V1Workaround;
|
||||||
|
if(!didGlVersionCheck) {
|
||||||
|
didGlVersionCheck = true;
|
||||||
|
if(!strcmp((const char*) glGetString(GL_VERSION), "1.1.0")) {
|
||||||
|
// The default Windows GL renderer really does implement GL 1.1,
|
||||||
|
// and cannot handle non-power-of-2 textures, which is legal.
|
||||||
|
needsGl1V1Workaround = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return needsGl1V1Workaround;
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGl1Renderer::SelectTexture(std::shared_ptr<const Pixmap> pm) {
|
void OpenGl1Renderer::SelectTexture(std::shared_ptr<const Pixmap> pm) {
|
||||||
if(current.texture.lock() == pm) return;
|
if(current.texture.lock() == pm) return;
|
||||||
|
|
||||||
@ -220,8 +245,19 @@ void OpenGl1Renderer::SelectTexture(std::shared_ptr<const Pixmap> pm) {
|
|||||||
case Pixmap::Format::BGR:
|
case Pixmap::Format::BGR:
|
||||||
ssassert(false, "Unexpected pixmap format");
|
ssassert(false, "Unexpected pixmap format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!NeedsGl1V1Workaround()) {
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, format, pm->width, pm->height, 0,
|
glTexImage2D(GL_TEXTURE_2D, 0, format, pm->width, pm->height, 0,
|
||||||
format, GL_UNSIGNED_BYTE, &pm->data[0]);
|
format, GL_UNSIGNED_BYTE, &pm->data[0]);
|
||||||
|
} else {
|
||||||
|
GLsizei width = RoundUpToPowerOfTwo(pm->width);
|
||||||
|
GLsizei height = RoundUpToPowerOfTwo(pm->height);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
|
||||||
|
format, GL_UNSIGNED_BYTE, 0);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pm->width, pm->height,
|
||||||
|
format, GL_UNSIGNED_BYTE, &pm->data[0]);
|
||||||
|
}
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
current.texture = pm;
|
current.texture = pm;
|
||||||
@ -603,17 +639,24 @@ void OpenGl1Renderer::DrawFaces(const SMesh &m, const std::vector<uint32_t> &fac
|
|||||||
void OpenGl1Renderer::DrawPixmap(std::shared_ptr<const Pixmap> pm,
|
void OpenGl1Renderer::DrawPixmap(std::shared_ptr<const Pixmap> pm,
|
||||||
const Vector &o, const Vector &u, const Vector &v,
|
const Vector &o, const Vector &u, const Vector &v,
|
||||||
const Point2d &ta, const Point2d &tb, hFill hcf) {
|
const Point2d &ta, const Point2d &tb, hFill hcf) {
|
||||||
|
double xfactor = 1.0,
|
||||||
|
yfactor = 1.0;
|
||||||
|
if(NeedsGl1V1Workaround()) {
|
||||||
|
xfactor = (double)pm->width / RoundUpToPowerOfTwo(pm->width);
|
||||||
|
yfactor = (double)pm->height / RoundUpToPowerOfTwo(pm->height);
|
||||||
|
}
|
||||||
|
|
||||||
UnSelectPrimitive();
|
UnSelectPrimitive();
|
||||||
SelectFill(hcf);
|
SelectFill(hcf);
|
||||||
SelectTexture(pm);
|
SelectTexture(pm);
|
||||||
SelectPrimitive(GL_QUADS);
|
SelectPrimitive(GL_QUADS);
|
||||||
glTexCoord2d(ta.x, ta.y);
|
glTexCoord2d(ta.x * xfactor, ta.y * yfactor);
|
||||||
ssglVertex3v(o);
|
ssglVertex3v(o);
|
||||||
glTexCoord2d(ta.x, tb.y);
|
glTexCoord2d(ta.x * xfactor, tb.y * yfactor);
|
||||||
ssglVertex3v(o.Plus(v));
|
ssglVertex3v(o.Plus(v));
|
||||||
glTexCoord2d(tb.x, tb.y);
|
glTexCoord2d(tb.x * xfactor, tb.y * yfactor);
|
||||||
ssglVertex3v(o.Plus(u).Plus(v));
|
ssglVertex3v(o.Plus(u).Plus(v));
|
||||||
glTexCoord2d(tb.x, ta.y);
|
glTexCoord2d(tb.x * xfactor, ta.y * yfactor);
|
||||||
ssglVertex3v(o.Plus(u));
|
ssglVertex3v(o.Plus(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user