diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index 573f3d099c..86ce0a68a7 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -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); diff --git a/src/add-ons/accelerants/intel_extreme/commands.h b/src/add-ons/accelerants/intel_extreme/commands.h new file mode 100644 index 0000000000..aabdd9ecf4 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/commands.h @@ -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 diff --git a/src/add-ons/accelerants/intel_extreme/engine.cpp b/src/add-ons/accelerants/intel_extreme/engine.cpp index 6fd9bac195..a7e5ab894e 100644 --- a/src/add-ons/accelerants/intel_extreme/engine.cpp +++ b/src/add-ons/accelerants/intel_extreme/engine.cpp @@ -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 + diff --git a/src/add-ons/accelerants/intel_extreme/overlay.cpp b/src/add-ons/accelerants/intel_extreme/overlay.cpp index e4af605fa2..aa6697cd98 100644 --- a/src/add-ons/accelerants/intel_extreme/overlay.cpp +++ b/src/add-ons/accelerants/intel_extreme/overlay.cpp @@ -12,6 +12,7 @@ #include "accelerant.h" #include "accelerant_protos.h" +#include "commands.h" #include #include @@ -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; }