Ejemplo n.º 1
0
void Display(void) {
    int im_size_2 = im_size / 2;
    glClear(GL_COLOR_BUFFER_BIT);
    // rysowanie pikseli od lewego górnego narożnika do prawego dolnego narożnika
    DrawPixels(-im_size_2, im_size_2, im_size_2, 0);
    DrawPixels(-im_size_2, 0, im_size_2, -im_size_2);
    glFlush();
}
Ejemplo n.º 2
0
void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) {
	addr &= ~0x40000000;
	// TODO: Could go through all FBOs, but probably not important?
	// TODO: Could also check for inner changes, but video is most important.
	bool isDisplayBuf = addr == DisplayFramebufAddr() || addr == PrevDisplayFramebufAddr();
	if (isDisplayBuf || safe) {
		// TODO: Deleting the FBO is a heavy hammer solution, so let's only do it if it'd help.
		if (!Memory::IsValidAddress(displayFramebufPtr_))
			return;

		for (size_t i = 0; i < vfbs_.size(); ++i) {
			VirtualFramebuffer *vfb = vfbs_[i];
			if (MaskedEqual(vfb->fb_address, addr)) {
				FlushBeforeCopy();

				if (useBufferedRendering_ && vfb->fbo) {
					DisableState();
					GEBufferFormat fmt = vfb->format;
					if (vfb->last_frame_render + 1 < gpuStats.numFlips && isDisplayBuf) {
						// If we're not rendering to it, format may be wrong.  Use displayFormat_ instead.
						fmt = displayFormat_;
					}
					DrawPixels(vfb, 0, 0, Memory::GetPointer(addr | 0x04000000), fmt, vfb->fb_stride, vfb->width, vfb->height);
					SetColorUpdated(vfb);
				} else {
					INFO_LOG(SCEGE, "Invalidating FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format);
					DestroyFramebuf(vfb);
					vfbs_.erase(vfbs_.begin() + i--);
				}
			}
		}

		RebindFramebuffer();
	}
}
Ejemplo n.º 3
0
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HINSTANCE hInstance = GetModuleHandle(NULL);
    switch(msg)
    {
		case WM_CREATE:
    
			hBitmap = (HBITMAP) LoadImageW(NULL, L"sticker.bmp", 
                IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

			if (hBitmap == NULL) {
				MessageBoxW(hwnd, L"Failed to load image", L"Error", MB_OK); 
			}

        break;      
		case WM_PAINT:
			DrawPixels(hwnd);
		break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}
Ejemplo n.º 4
0
bool CVobSubImage::Decode(BYTE* lpData, int packetsize, int datasize,
                          bool fCustomPal,
                          int tridx,
                          RGBQUAD* orgpal /*[16]*/, RGBQUAD* cuspal /*[4]*/,
                          bool fTrim)
{
    GetPacketInfo(lpData, packetsize, datasize);

    if(!Alloc(rect.Width(), rect.Height())) {
        return(false);
    }

    lpPixels = lpTemp1;

    nPlane = 0;
    fAligned = 1;

    this->fCustomPal = fCustomPal;
    this->orgpal = orgpal;
    this->tridx = tridx;
    this->cuspal = cuspal;

    CPoint p(rect.left, rect.top);

    int end0 = nOffset[1];
    int end1 = datasize;

    while((nPlane == 0 && nOffset[0] < end0) || (nPlane == 1 && nOffset[1] < end1)) {
        DWORD code;

        if((code = GetNibble(lpData)) >= 0x4
                || (code = (code << 4) | GetNibble(lpData)) >= 0x10
                || (code = (code << 4) | GetNibble(lpData)) >= 0x40
                || (code = (code << 4) | GetNibble(lpData)) >= 0x100) {
            DrawPixels(p, code >> 2, code & 3);
            if((p.x += code >> 2) < rect.right) {
                continue;
            }
        }

        DrawPixels(p, rect.right - p.x, code & 3);

        if(!fAligned) {
            GetNibble(lpData);    // align to byte
        }

        p.x = rect.left;
        p.y++;
        nPlane = 1 - nPlane;
    }
Ejemplo n.º 5
0
void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int width, int height, int bpp, u32 skipDrawReason) {
	// A few games use this INSTEAD of actually drawing the video image to the screen, they just blast it to
	// the backbuffer. Detect this and have the framebuffermanager draw the pixels.

	u32 backBuffer = PrevDisplayFramebufAddr();
	u32 displayBuffer = DisplayFramebufAddr();

	// TODO: Is this not handled by upload?  Should we check !dstBuffer to avoid a double copy?
	if (((backBuffer != 0 && dstBasePtr == backBuffer) ||
		(displayBuffer != 0 && dstBasePtr == displayBuffer)) &&
		dstStride == 512 && height == 272 && !useBufferedRendering_) {
		FlushBeforeCopy();
		DrawFramebufferToOutput(Memory::GetPointerUnchecked(dstBasePtr), displayFormat_, 512, false);
	}

	if (MayIntersectFramebuffer(srcBasePtr) || MayIntersectFramebuffer(dstBasePtr)) {
		VirtualFramebuffer *dstBuffer = 0;
		VirtualFramebuffer *srcBuffer = 0;
		int srcWidth = width;
		int srcHeight = height;
		int dstWidth = width;
		int dstHeight = height;
		FindTransferFramebuffers(dstBuffer, srcBuffer, dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, srcWidth, srcHeight, dstWidth, dstHeight, bpp);

		if (!useBufferedRendering_ && currentRenderVfb_ != dstBuffer) {
			return;
		}

		if (dstBuffer && !srcBuffer) {
			WARN_LOG_ONCE(btu, G3D, "Block transfer upload %08x -> %08x", srcBasePtr, dstBasePtr);
			if (g_Config.bBlockTransferGPU) {
				FlushBeforeCopy();
				const u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp;
				int dstBpp = dstBuffer->format == GE_FORMAT_8888 ? 4 : 2;
				float dstXFactor = (float)bpp / dstBpp;
				if (dstWidth > dstBuffer->width || dstHeight > dstBuffer->height) {
					// The buffer isn't big enough, and we have a clear hint of size.  Resize.
					// This happens in Valkyrie Profile when uploading video at the ending.
					ResizeFramebufFBO(dstBuffer, dstWidth, dstHeight, false, true);
				}
				DrawPixels(dstBuffer, static_cast<int>(dstX * dstXFactor), dstY, srcBase, dstBuffer->format, static_cast<int>(srcStride * dstXFactor), static_cast<int>(dstWidth * dstXFactor), dstHeight);
				SetColorUpdated(dstBuffer, skipDrawReason);
				RebindFramebuffer();
			}
		}
	}
}
Ejemplo n.º 6
0
	// функция получает два отрезка и закрашивает пространство между ними
	// заранее известно, что у каждого отрезка первая точка имеет Y не больше чем вторая
	// а также p левее q
	inline static void FillInside(const Segment& p, const Segment& q, const Color& color, const SDLApplication* app, Scene3D* scene)
	{
		const int ystart = std::max(0, static_cast<int>(ceil(std::max(p.first.p[1], q.first.p[1]))));
		const int yfinish = std::min(app->Screen->h - 1, static_cast<int>(floor(std::min(p.second.p[1], q.second.p[1]))));

		// d##_dy - это производная ## по y (константа, так как эти переменные линейны по x и по y), смысл переменных ## - объяснен ниже
		// если отрезок p горизонтален, то dpw_dy, dpx_dy не имеет смысла, так что пусть будет 0
		const double dpw_dy = (p.second.p[1] == p.first.p[1]) ? 0 : (p.second.w - p.first.w) / (p.second.p[1] - p.first.p[1]);
		const double dpx_dy = (p.second.p[1] == p.first.p[1]) ? 0 : (p.second.p[0] - p.first.p[0]) / (p.second.p[1] - p.first.p[1]);

		// если отрезок q горизонтален, то dqw_dy, dqx_dy не имеет смысла, так что пусть будет 0
		const double dqw_dy = (q.second.p[1] == q.first.p[1]) ? 0 : (q.second.w - q.first.w) / (q.second.p[1] - q.first.p[1]);
		const double dqx_dy = (q.second.p[1] == q.first.p[1]) ? 0 : (q.second.p[0] - q.first.p[0]) / (q.second.p[1] - q.first.p[1]);

		// нахождение dw_dx
		// кроме вырожденных случаев, только на одном y выполняется deltax = qx - px == 0 (в точке пересечения)
		// так как dw_dx не зависит от y, то можно сложить равенства deltaw = deltax * dw_dx, для двух разных y
		// и получить (deltaw1 + deltaw2) = (deltax1 + deltax2) * dw_dx
		// dw_dx = (deltaw1 + deltaw2) / (deltax1 + deltax2)
		// возьмем в качестве двух разных y ystart и yfinish
		// в знаменателе будет 0 только в вырожденном случае (если ystart = yfinish = ординате точки пересечения)
		// в этом случае рисуем только одну точку и dw_dx не имеет значения
		const double deltax1 = (q.first.p[0] + (ystart - q.first.p[1]) * dqx_dy) - (p.first.p[0] + (ystart - p.first.p[1]) * dpx_dy);
		const double deltax2 = (q.first.p[0] + (yfinish - q.first.p[1]) * dqx_dy) - (p.first.p[0] + (yfinish - p.first.p[1]) * dpx_dy);
		const double deltaw1 = (q.first.w + (ystart - q.first.p[1]) * dqw_dy) - (p.first.w + (ystart - p.first.p[1]) * dpw_dy);
		const double deltaw2 = (q.first.w + (yfinish - q.first.p[1]) * dqw_dy) - (p.first.w + (yfinish - p.first.p[1]) * dpw_dy);
		const double dw_dx = (deltax1 + deltax2 == 0) ? 0 : (deltaw1 + deltaw2) / (deltax1 + deltax2);

		// pw - это значение w в точке пересечения прямой, содержащей отрезок p и прямой Y = y, сейчас Y = ystart
		double pw = p.first.w + (ystart - p.first.p[1]) * dpw_dy;
		// px - это значение x в точке пересечения прямой, содержащей отрезок p и прямой Y = y, сейчас Y = ystart
		double px = p.first.p[0] + (ystart - p.first.p[1]) * dpx_dy;
		// qx - это значение x в точке пересечения прямой, содержащей отрезок q и прямой Y = y, сейчас Y = ystart
		double qx = q.first.p[0] + (ystart - q.first.p[1]) * dqx_dy;

		for(int y = ystart; y <= yfinish; ++y)
		{
			DrawPixels(px, qx, pw, dw_dx, y, color, app, scene);

			pw += dpw_dy;
			px += dpx_dy;
			qx += dqx_dy;
		}
	}
Ejemplo n.º 7
0
bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset) {
	if (updateVRAM_ || size == 0) {
		return false;
	}

	dst &= 0x3FFFFFFF;
	src &= 0x3FFFFFFF;

	VirtualFramebuffer *dstBuffer = 0;
	VirtualFramebuffer *srcBuffer = 0;
	u32 dstY = (u32)-1;
	u32 dstH = 0;
	u32 srcY = (u32)-1;
	u32 srcH = 0;
	for (size_t i = 0; i < vfbs_.size(); ++i) {
		VirtualFramebuffer *vfb = vfbs_[i];
		if (vfb->fb_stride == 0) {
			continue;
		}

		const u32 vfb_address = (0x04000000 | vfb->fb_address) & 0x3FFFFFFF;
		const u32 vfb_size = FramebufferByteSize(vfb);
		const u32 vfb_bpp = vfb->format == GE_FORMAT_8888 ? 4 : 2;
		const u32 vfb_byteStride = vfb->fb_stride * vfb_bpp;
		const int vfb_byteWidth = vfb->width * vfb_bpp;

		if (dst >= vfb_address && (dst + size <= vfb_address + vfb_size || dst == vfb_address)) {
			const u32 offset = dst - vfb_address;
			const u32 yOffset = offset / vfb_byteStride;
			if ((offset % vfb_byteStride) == 0 && (size == vfb_byteWidth || (size % vfb_byteStride) == 0) && yOffset < dstY) {
				dstBuffer = vfb;
				dstY = yOffset;
				dstH = size == vfb_byteWidth ? 1 : std::min((u32)size / vfb_byteStride, (u32)vfb->height);
			}
		}

		if (src >= vfb_address && (src + size <= vfb_address + vfb_size || src == vfb_address)) {
			const u32 offset = src - vfb_address;
			const u32 yOffset = offset / vfb_byteStride;
			if ((offset % vfb_byteStride) == 0 && (size == vfb_byteWidth || (size % vfb_byteStride) == 0) && yOffset < srcY) {
				srcBuffer = vfb;
				srcY = yOffset;
				srcH = size == vfb_byteWidth ? 1 : std::min((u32)size / vfb_byteStride, (u32)vfb->height);
			} else if ((offset % vfb_byteStride) == 0 && size == vfb->fb_stride && yOffset < srcY) {
				// Valkyrie Profile reads 512 bytes at a time, rather than 2048.  So, let's whitelist fb_stride also.
				srcBuffer = vfb;
				srcY = yOffset;
				srcH = 1;
			}
		}
	}

	if (srcBuffer && srcY == 0 && srcH == srcBuffer->height && !dstBuffer) {
		// MotoGP workaround - it copies a framebuffer to memory and then displays it.
		// TODO: It's rare anyway, but the game could modify the RAM and then we'd display the wrong thing.
		// Unfortunately, that would force 1x render resolution.
		if (Memory::IsRAMAddress(dst)) {
			knownFramebufferRAMCopies_.insert(std::pair<u32, u32>(src, dst));
		}
	}

	if (!useBufferedRendering_) {
		// If we're copying into a recently used display buf, it's probably destined for the screen.
		if (srcBuffer || (dstBuffer != displayFramebuf_ && dstBuffer != prevDisplayFramebuf_)) {
			return false;
		}
	}

	if (dstBuffer && srcBuffer && !isMemset) {
		if (srcBuffer == dstBuffer) {
			WARN_LOG_REPORT_ONCE(dstsrccpy, G3D, "Intra-buffer memcpy (not supported) %08x -> %08x", src, dst);
		} else {
			WARN_LOG_REPORT_ONCE(dstnotsrccpy, G3D, "Inter-buffer memcpy %08x -> %08x", src, dst);
			// Just do the blit!
			if (g_Config.bBlockTransferGPU) {
				BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0);
				SetColorUpdated(dstBuffer);
				RebindFramebuffer();
			}
		}
		return false;
	} else if (dstBuffer) {
		WARN_LOG_ONCE(btucpy, G3D, "Memcpy fbo upload %08x -> %08x", src, dst);
		if (g_Config.bBlockTransferGPU) {
			FlushBeforeCopy();
			const u8 *srcBase = Memory::GetPointerUnchecked(src);
			DrawPixels(dstBuffer, 0, dstY, srcBase, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstH);
			SetColorUpdated(dstBuffer);
			RebindFramebuffer();
			// This is a memcpy, let's still copy just in case.
			return false;
		}
		return false;
	} else if (srcBuffer) {
		WARN_LOG_ONCE(btdcpy, G3D, "Memcpy fbo download %08x -> %08x", src, dst);
		FlushBeforeCopy();
		if (srcH == 0 || srcY + srcH > srcBuffer->bufferHeight) {
			WARN_LOG_REPORT_ONCE(btdcpyheight, G3D, "Memcpy fbo download %08x -> %08x skipped, %d+%d is taller than %d", src, dst, srcY, srcH, srcBuffer->bufferHeight);
		} else if (g_Config.bBlockTransferGPU && !srcBuffer->memoryUpdated) {
			ReadFramebufferToMemory(srcBuffer, true, 0, srcY, srcBuffer->width, srcH);
		}
		return false;
	} else {
		return false;
	}
}
Ejemplo n.º 8
0
void
DrawScene(void)
{

    /* clear the draw buffer */
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    // clear the rasterization framebuffer
    memset(framebuffer, 0, 3*framebuffer_width*framebuffer_height);

    if (scene == 1)
        DrawTriangles();
    else if (scene == 2)
        TestRasterizationSpeed();
    else if (scene == 4)
        DrawPixels();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    if (scene != 9)
    {
        if (zoom)
            glOrtho(0, framebuffer_width, 0, framebuffer_height, -1, 1);
        else
            glOrtho(0, screen_width, 0, screen_height, -1, 1);

        // Draw textured quad

        glEnable(GL_TEXTURE_2D);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
            framebuffer_width, framebuffer_height,
            0, GL_RGB, GL_UNSIGNED_BYTE, framebuffer);

        glColor3f(1, 1, 1);
        glBegin(GL_QUADS);
            glTexCoord2i(0, 0);
            glVertex2i(0, 0);
            glTexCoord2i(1, 0);
            glVertex2i(framebuffer_width, 0);
            glTexCoord2i(1, 1);
            glVertex2i(framebuffer_width, framebuffer_height);
            glTexCoord2i(0, 1);
            glVertex2i(0, framebuffer_height);
        glEnd();
    }
    else
    {
        if (zoom)
            glOrtho(-0.5, framebuffer_width-0.5, -0.5, framebuffer_height-0.5, -1, 1);
        else
            glOrtho(-0.5, screen_width-0.5, -0.5, screen_height-0.5, -1, 1);

        DrawTrianglesOpenGL();

        glDisable(GL_TEXTURE_2D);
        glColor3f(1, 1, 0);
        glBegin(GL_POINTS);
            glVertex2i(0, 0);
            glVertex2i(framebuffer_width-1, framebuffer_height-1);
        glEnd();

    }

    // finally, swap the draw buffers to make the triangles appear on screen
    glutSwapBuffers();
}