Prepared support for acceleration: there is now a QueueCommands class that should
be used to feed the ring buffers with new commands. It takes care about proper alignment (this shouldn't be necessary in the final version, anymore, though), and locking. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fc88cd9396
commit
6c67d64cad
@ -77,8 +77,6 @@ extern void set_display_power_mode(uint32 mode);
|
||||
|
||||
// engine.cpp
|
||||
extern void setup_ring_buffer(ring_buffer &ringBuffer, const char *name);
|
||||
extern void write_to_ring(ring_buffer &ring, uint32 value);
|
||||
extern void ring_command_complete(ring_buffer &ring);
|
||||
|
||||
// modes.cpp
|
||||
extern status_t create_mode_list(void);
|
||||
|
43
src/add-ons/accelerants/intel_extreme/commands.h
Normal file
43
src/add-ons/accelerants/intel_extreme/commands.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
#ifndef COMMANDS_H
|
||||
#define COMMANDS_H
|
||||
|
||||
|
||||
#include "accelerant.h"
|
||||
|
||||
|
||||
struct command {
|
||||
uint32 opcode;
|
||||
|
||||
uint32 *Data() { return &opcode; }
|
||||
virtual size_t Length() = 0;
|
||||
};
|
||||
|
||||
class QueueCommands {
|
||||
public:
|
||||
QueueCommands(ring_buffer &ring);
|
||||
~QueueCommands();
|
||||
|
||||
void Put(struct command &command);
|
||||
void PutFlush();
|
||||
void PutWaitFor(uint32 event);
|
||||
void PutOverlayFlip(uint32 code, bool updateCoefficients);
|
||||
|
||||
private:
|
||||
void _MakeSpace(uint32 size);
|
||||
void _Write(uint32 data);
|
||||
|
||||
ring_buffer &fRingBuffer;
|
||||
};
|
||||
|
||||
|
||||
// commands
|
||||
|
||||
|
||||
#endif // COMMANDS_H
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "accelerant_protos.h"
|
||||
#include "commands.h"
|
||||
|
||||
|
||||
#define TRACE_ENGINE
|
||||
@ -23,37 +24,96 @@ extern "C" void _sPrintf(const char *format, ...);
|
||||
static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL};
|
||||
|
||||
|
||||
/** The ring buffer must be locked when calling this function */
|
||||
|
||||
void
|
||||
write_to_ring(ring_buffer &ring, uint32 value)
|
||||
QueueCommands::QueueCommands(ring_buffer &ring)
|
||||
:
|
||||
fRingBuffer(ring)
|
||||
{
|
||||
uint32 *target = (uint32 *)(ring.base + ring.position);
|
||||
*target = value;
|
||||
|
||||
ring.position = (ring.position + sizeof(uint32)) & (ring.size - 1);
|
||||
acquire_lock(&fRingBuffer.lock);
|
||||
}
|
||||
|
||||
|
||||
/** The ring buffer must be locked when calling this function */
|
||||
|
||||
void
|
||||
ring_command_complete(ring_buffer &ring)
|
||||
QueueCommands::~QueueCommands()
|
||||
{
|
||||
if (ring.position & 0x07) {
|
||||
if (fRingBuffer.position & 0x07) {
|
||||
// make sure the command is properly aligned
|
||||
write_to_ring(ring, COMMAND_NOOP);
|
||||
_Write(COMMAND_NOOP);
|
||||
}
|
||||
|
||||
write32(ring.register_base + RING_BUFFER_TAIL, ring.position);
|
||||
write32(fRingBuffer.register_base + RING_BUFFER_TAIL, fRingBuffer.position);
|
||||
|
||||
// make sure memory is written back in case the ring buffer
|
||||
// is in write combining mode
|
||||
int32 test;
|
||||
atomic_add(&test, 1);
|
||||
// We must make sure memory is written back in case the ring buffer
|
||||
// is in write combining mode - releasing the lock does this, as the
|
||||
// buffer is flushed on a locked memory operation (which is what this
|
||||
// benaphore does)
|
||||
release_lock(&fRingBuffer.lock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueCommands::Put(struct command &command)
|
||||
{
|
||||
uint32 count = command.Length();
|
||||
uint32 *data = command.Data();
|
||||
|
||||
_MakeSpace(count);
|
||||
|
||||
for (uint32 i = 0; i < count; i++) {
|
||||
_Write(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueCommands::PutFlush()
|
||||
{
|
||||
_MakeSpace(2);
|
||||
|
||||
_Write(COMMAND_FLUSH);
|
||||
_Write(COMMAND_NOOP);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueCommands::PutWaitFor(uint32 event)
|
||||
{
|
||||
_MakeSpace(2);
|
||||
|
||||
_Write(COMMAND_WAIT_FOR_EVENT | event);
|
||||
_Write(COMMAND_NOOP);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueCommands::PutOverlayFlip(uint32 mode, bool updateCoefficients)
|
||||
{
|
||||
_MakeSpace(2);
|
||||
|
||||
_Write(COMMAND_OVERLAY_FLIP | mode);
|
||||
_Write((uint32)gInfo->shared_info->physical_overlay_registers
|
||||
| (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueCommands::_MakeSpace(uint32 size)
|
||||
{
|
||||
// TODO: make sure there is enough room to write the command!
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
QueueCommands::_Write(uint32 data)
|
||||
{
|
||||
uint32 *target = (uint32 *)(fRingBuffer.base + fRingBuffer.position);
|
||||
*target = data;
|
||||
|
||||
fRingBuffer.position = (fRingBuffer.position + sizeof(uint32)) & (fRingBuffer.size - 1);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
setup_ring_buffer(ring_buffer &ringBuffer, const char *name)
|
||||
{
|
||||
@ -75,7 +135,7 @@ setup_ring_buffer(ring_buffer &ringBuffer, const char *name)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// #pragma mark - engine management
|
||||
|
||||
|
||||
/** Return number of hardware engines */
|
||||
@ -132,3 +192,6 @@ intel_sync_to_token(sync_token *syncToken)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - engine acceleration
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "accelerant_protos.h"
|
||||
#include "commands.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
@ -225,19 +226,14 @@ update_overlay(bool updateCoefficients)
|
||||
if (!gInfo->shared_info->overlay_active)
|
||||
return;
|
||||
|
||||
ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer;
|
||||
write_to_ring(ringBuffer, COMMAND_FLUSH);
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE);
|
||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
|
||||
| (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0));
|
||||
ring_command_complete(ringBuffer);
|
||||
QueueCommands queue(gInfo->shared_info->secondary_ring_buffer);
|
||||
queue.PutFlush();
|
||||
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, updateCoefficients);
|
||||
|
||||
TRACE(("update overlay: UPDATE: %lx, TEST: %lx, STATUS: %lx, EXTENDED_STATUS: %lx\n",
|
||||
read32(INTEL_OVERLAY_UPDATE), read32(INTEL_OVERLAY_TEST), read32(INTEL_OVERLAY_STATUS),
|
||||
read32(INTEL_OVERLAY_EXTENDED_STATUS)));
|
||||
// TRACE(("update overlay: UPDATE: %lx, TEST: %lx, STATUS: %lx, EXTENDED_STATUS: %lx\n",
|
||||
// read32(INTEL_OVERLAY_UPDATE), read32(INTEL_OVERLAY_TEST), read32(INTEL_OVERLAY_STATUS),
|
||||
// read32(INTEL_OVERLAY_EXTENDED_STATUS)));
|
||||
}
|
||||
|
||||
|
||||
@ -252,13 +248,9 @@ show_overlay(void)
|
||||
gInfo->shared_info->overlay_active = true;
|
||||
registers->overlay_enabled = true;
|
||||
|
||||
ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer;
|
||||
write_to_ring(ringBuffer, COMMAND_FLUSH);
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_ON);
|
||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
|
||||
| OVERLAY_UPDATE_COEFFICIENTS);
|
||||
ring_command_complete(ringBuffer);
|
||||
QueueCommands queue(gInfo->shared_info->secondary_ring_buffer);
|
||||
queue.PutFlush();
|
||||
queue.PutOverlayFlip(COMMAND_OVERLAY_ON, true);
|
||||
}
|
||||
|
||||
|
||||
@ -273,26 +265,19 @@ hide_overlay(void)
|
||||
gInfo->shared_info->overlay_active = false;
|
||||
registers->overlay_enabled = false;
|
||||
|
||||
ring_buffer &ringBuffer = gInfo->shared_info->secondary_ring_buffer;
|
||||
QueueCommands queue(gInfo->shared_info->secondary_ring_buffer);
|
||||
|
||||
// flush pending commands
|
||||
write_to_ring(ringBuffer, COMMAND_FLUSH);
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
queue.PutFlush();
|
||||
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
|
||||
// clear overlay enabled bit
|
||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE);
|
||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers);
|
||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, false);
|
||||
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
|
||||
// turn off overlay engine
|
||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_OFF);
|
||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers);
|
||||
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
ring_command_complete(ringBuffer);
|
||||
queue.PutOverlayFlip(COMMAND_OVERLAY_OFF, false);
|
||||
queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
|
||||
|
||||
gInfo->current_overlay = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user