| 2370 | } |
| 2371 | |
| 2372 | void GSState::FlushWrite() |
| 2373 | { |
| 2374 | if (!m_tr.write) |
| 2375 | return; |
| 2376 | |
| 2377 | const int len = m_tr.end - m_tr.start; |
| 2378 | |
| 2379 | if (len <= 0) |
| 2380 | return; |
| 2381 | |
| 2382 | GSVector4i r; |
| 2383 | |
| 2384 | r = m_tr.rect; |
| 2385 | |
| 2386 | // If the end isn't where it said it would be, we need to calculate the end point. |
| 2387 | // Star Wars - The Clone Wars just sets the rect to 16x4095 then YOLO's about half a page, then kills the transfer. |
| 2388 | // If we just nuke the whole lot, even though nothing has been transferred, we risk killing data we don't mean to. |
| 2389 | if (m_tr.end < m_tr.total && GSIsHardwareRenderer()) |
| 2390 | { |
| 2391 | const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[m_tr.m_blit.DPSM]; |
| 2392 | // Convert to nibbles then back to bytes after, in case trbpp is 4. |
| 2393 | const u32 in_data_pixel_count = (((len * 2) + ((psm_s.trbpp / 4) - 1)) / (psm_s.trbpp / 4)); |
| 2394 | const u32 rect_pixel_count = r.width() * r.height(); |
| 2395 | |
| 2396 | if (rect_pixel_count > in_data_pixel_count) |
| 2397 | { |
| 2398 | const int calculated_height = ((in_data_pixel_count + (r.width() - 1)) / r.width()); |
| 2399 | |
| 2400 | // Just setting the height should be okay... |
| 2401 | r.w = std::max(r.y + calculated_height, psm_s.bs.y); |
| 2402 | |
| 2403 | if (m_draw_transfers.size() > 0 && m_tr.m_blit.DBP == m_draw_transfers.back().blit.DBP) |
| 2404 | { |
| 2405 | m_draw_transfers.back().rect = m_draw_transfers.back().rect.runion(r); |
| 2406 | } |
| 2407 | } |
| 2408 | } |
| 2409 | |
| 2410 | InvalidateVideoMem(m_env.BITBLTBUF, r); |
| 2411 | |
| 2412 | const GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi; |
| 2413 | |
| 2414 | wi(m_mem, m_tr.x, m_tr.y, &m_tr.buff[m_tr.start], len, m_tr.m_blit, m_tr.m_pos, m_tr.m_reg); |
| 2415 | |
| 2416 | m_tr.start += len; |
| 2417 | |
| 2418 | g_perfmon.Put(GSPerfMon::Swizzle, len); |
| 2419 | s_transfer_n++; |
| 2420 | if (m_tr.start >= m_tr.total) |
| 2421 | m_env.TRXDIR.XDIR = 3; |
| 2422 | } |
| 2423 | |
| 2424 | // This function decides if the context has changed in a way which warrants flushing the draw. |
| 2425 | inline bool GSState::TestDrawChanged() |
nothing calls this directly
no test coverage detected