LockRect -> invalid call
-
Ich werd mal Ausführlicher, vielleicht hilft das ja.
Als erstes das Device anlegen://Direct3D-Gerät anlegen HRESULT hr; if(FAILED(hr = m_lpD3D->CreateDevice( D3DADAPTER_DEFAULT, //verwende die primäre Grafikkarte D3DDEVTYPE_HAL, //verwende Hardwareunterstützung hWnd, //Fensterhandle D3DCREATE_SOFTWARE_VERTEXPROCESSING, //Softwareemulierte Vertexberechnung &PParams, //Backbuffereigenschaften &m_lpD3DDevice))) //Struktur zum ablegen der Deviceinformationen { //Fehler, kann Gerät nicht anlegen const char *Err = DXGetErrorDescription(hr); DXTRACE_MSG(Err); return FALSE; }
PParams ist wie folgt festgelegt:
//Parameter für den Modus festlegen D3DPRESENT_PARAMETERS PParams; //Struktur zum festlegen der Backbuffereigenschaften ZeroMemory(&PParams, sizeof(PParams)); //Allokiert Speicher für das obige Struct PParams.SwapEffect = D3DSWAPEFFECT_DISCARD; //Backbuffer auf schnellst mögliche Art anzeigen PParams.hDeviceWindow = hWnd; //Fensterhandle PParams.Windowed = bWindowed; //Vollbild = FALSE, Fenster = TRUE PParams.BackBufferWidth = SCR_WIDTH; //horizontale Auflösung PParams.BackBufferHeight = SCR_HEIGHT; //vertikale Auflösung PParams.BackBufferFormat = D3DFMT_A8R8G8B8; //Farbtiefe bestimmen, hier 32bit (8bit alpha, 8bit rot, 8bit grün, 8bit blau)
So, jetzt den OffscreenPlainSurface:
//OffscreenPlainSurface erzeugen if(FAILED(hr = m_lpD3DDevice->CreateOffscreenPlainSurface( SCR_WIDTH, SCR_HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_lpOffscreenPlainSurface, 0))) { const char *Err = DXGetErrorDescription(hr); DXTRACE_MSG(Err); return FALSE; }
SCR_WIDTH und SCRHEIGHT sind Makros für die Auflösung. in meinem fall 800x600@32bit, (@32bit)wie man den Flags entnehmen kann.
Jetzt versuch ich den OffscreenPlainSurface zu Locken:
D3DLOCKED_RECT LockedRect = {0}; //Oberfläche für direkten Zugriff sperren HRESULT hr; if(FAILED(hr = lpSurface->LockRect(&LockedRect, 0, 0))) { const char *Err = DXGetErrorDescription(hr); DXTRACE_MSG(Err); }
Es wird kein Fehler ausgegeben, ergo hat das locken geklappt.
dann pitch berechnen und drauf zeichnen:int Pitch = LockedRect.Pitch / 4; D3DCOLOR* Pixels = (D3DCOLOR*)LockedRect.pBits; ... //Position für den Stern berechnen int index = ((int)m_y * Pitch + (int)m_x); //Länge berücksichtigen und Farbe wählen for(int i=0; i<m_Length; i++) { Pixels[index + i * Pitch] = StarColors[i]; }
So, hier ist Zeile 10 das Problem.
Sobald ich hier in das Pixelfeld schreiben will krieg ich die folgende Fehlermeldung:Eine Ausnahme (erste Chance) bei 0x00dd2207 in HalloWindows.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x04de8a90.
Unbehandelte Ausnahme bei 0x00dd2207 in HalloWindows.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x04de8a90.Die Adressen sind naürlich immer andere, aber immer relativ zum Adressraum des Pixelfeldes.
Vielleicht hilft euch das ja mir zu Helfen^^
Weiß echt nicht, wo ich noch einfluss auf Zugriffsrechte habe, die werden doch eigentlich drch das Betriebssystem gesetzt. In meinem Fall Vista. IDE ist Visual C++ 2008 Express Edition. DirectX ist June 2010.thx so far
euer Shane
-
Hab grad noch den Versuch unternommen, das ganze im Vollbildmodus laufen zu lassen, weil im Fenstermodus evtl. irgendwelche rechte nicht gegeben waren, aber da funktioniert es auch nicht. Im nachhinein auch logisch, aber ein versuch war es mir wert. Im Vollbildmodus schmiert auch vc++ irgendwie ab und man kann nicht mal mehr zwischen den Fenstern hin und her schalten. das einzige was da funktioniert hat war das ausführen des Taskmanagers via STRG+ALT+ENTF. Glaub ich ein fehler von VC++ 2008.
thx so far
euer Shane
-
Was mir beim schnellen Überfliegen mal auffällt: Der Pitch ist die Anzahl der Bytes pro Zeile, nicht der Pixel...
-
richtig, deswegen teile ich ihn durch die Farbtiefe, um ihn auf die anzahl der Pixel pro Zeile zu bringen, da 32bit farbtiefe = 4 byte, ist pitch / 4 = anzahl der pixel in jeder zeile.
-
Hm ok übersehen sry. Ich würd mich aber nicht drauf verlassen dass der Pitch immer ein vielfaches von 4 ist...
Wo machst du eigentlich dein UnlockRect()?
-
der pitch ist doch abhängig von der Farbtiefe, die ich im falle meines programmes auf 32bit festgelegt habe. sowohl der backbuffer als auch mein offscreenplainsurface haben 32bit.
UnlockRect habe ich hier nur nicht mit aufgeführt. im programm stehts, aber da kommt der nie hin, weil er beim schreiben der pixeldaten hängen bleibt.
-
Der Pitch hängt natürlich mit der Farbtiefe zusammen er ist aber nicht notwendigerweise einfach Breite * sizeof(Pixel), dann bräuchte man ja keinen extra Pitch oder?
. Je nachdem wie die Graka das Ding im Speicher alignen will etc. kann der Pitch einfach irgendwas sein...
Wegen dem UnlockRect(): Wollte nur sichergehen dass es auch nach dem Schreiben steht und nicht davor...
-
Das UnlockRect kommt auch definitiv nach dem Schreiben.
Hm, wegen dem Pitch. Soweit ich weiß gibt es den, weil noch additionale informationen zu den Pixeln gespeichert werden. Demnach gibt der Pitch die Zeilen Länge inclusive der additionalen infos in byte an.
Ist meine berechnung bezüglich des Pitch und die anschließende adressierung mit dem neuen pitch verkehrt?
-
shane_da_progga schrieb:
Ist meine berechnung bezüglich des Pitch und die anschließende adressierung mit dem neuen pitch verkehrt?
Sie basiert auf der nicht notwendigerweise korrekten Annahme dass der Pitch ein Vielfaches von 4 ist. Aber naja, üblicherweise ist das der Fall, also wird er Fehler eher nicht dort zu suchen sein...
-
Nun, ich habe mir selber nicht besonders viele gedanken zu dem Pitch gemacht, da ich der annamhme war, wdas dieser im Buch korrekt berechnet wird.
Aber mal angenommen er ist falsch berechnet, wie berechne ich den Pitch dann so, dass ich in als offset in meiner adressierung benutzen kann? Ich meine, wie finde ich raus, inwieweit er nun von meiner farbtiefe abhängig ist oder nicht.
Da ich im prinzip nichs anderes falsch machen kann, ist das meine einzige hoffnung^^
es sei denn, dass irgendwelche flags gesetzt werden müssen, auf die das buch, aus gründen der nicht-kompetenz, nicht eingegangen ist.
Ich finds echt schade, dass der code aus dem buch fehlerhaft ist.
-
Wo liegt das Problem? Der Pitch ist die Anzahl an Bytes die eine Zeile belegt. Das ist alles. Um zur nächsten Zeile zu gelangen spul einfach um Pitch Bytes vor und nicht Pitch / 4 DWORDs...
-
um einzelne pixel zu adressieren ist es notwendig das entsprechende byte in der zeile zu ermitteln, da muss ich den pitch früher oder später teilen.
-
Nein musst du nicht. Einzelne Pixel adressierst du mit x und y Koordinaten. Die y Koordinate entspricht der Zeile. y * Pitch gibt dir damit den Byteoffset von pBits zum Zeilenanfang. Und von dort gehst du dann x * sizeof(Pixel) (in deinem Fall also x DWORDs) weiter um zu deinem Pixel zu gelangen. An deiner Stelle würd ich sowieso mal diese ganze komische Indexberechnung da überprüfen, höchstwahrscheinlich liegt der Fehler eh dort. Check mal ob das was du da ausrechnest überhaupt noch in der Surface drinnen liegt...
-
OK. Das sind echt solide Informationen^^ danke, hab mich eh die ganze zeit gefragt, warum das im buch so steht. Probier das mal sofort aus.
-
Hmm, schade, aber gibt genau den gleichen fehler aus. Meine Indexbrechnung:
int index = ((int)m_y * Pitch + (int)(m_x * 4));
Der Pitch geht dabei unverändert in die Berechnung ein. m_y ist die y koordinate des Sterns, m_x entsprechend die x-Koordinate. /4, weil sizeof(D3DCOLOR_X8R8G8B8) letztenendes auch nur 4 rausschmeißt.
-
Der Unterschied zwischen einem Index und einer Adresse ist dir bekannt!? Was ich meinte war folgendes:
DWORD* pixel = reinterpret_cast<DWORD*>(static_cast<char*>(LockedRect.pBits) + y * LockedRect.Pitch) + x;
-
ja, der unterschied ist mir bekannt...
Ich habe einen index berechnet, um via pBits[index] eine Adresse zu erhalten. pBits ist ein Zeiger auf das erste Byte der Surface und man kann diesen auch als array von Bytes behandeln. Demnach muss man nur berechnen, das wievielte Byte ich veränder/setzen möchte und dieses via pBits[Index] ansprechen.
-
Stimmt, sry hab deinen Code zu flüchtig gelesen
-
Macht ja nix. Ich hätte wohl auch keinen Bock richtig hin zu lesen, wenn ich den mist schon 100 mal gemacht hätte
Ich gehe jetzt mal davon aus, das die Adressierung des Pixels klappt, dann gibt es immer noch den blöden Fehler. Ergo gibt es entweder eine Möglichkeit die Zugriffsrechte zu beeinflussen oder der Surface ist eben doch nicht richtig gelockt, obwohl kein Fehler ausgegeben wird.
Natürlich gibt es auch noch Option3, dass Directx auf dem Gebiet Veränderungen durchlaufen hat, die dem Buch selbstredend vorenthalten sind, da es zu directx9 Zeiten geschrieben wurde.
-
Ich würde zuerst mal Option 4 überprüfen: Du greifst auf Speicher zu der außerhalb der Surface liegt weil deine Koordinaten müll sind.